把redis源码的linux网络库提取出来,自己封装成通用库使用(1)(★firecat推荐★)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 把redis源码的linux网络库提取出来,自己封装成通用库使用(★firecat推荐★)

如题,redis网络库是基于单进程单线程的机制实现,简单高效。可用直接将它提取出来使用。Redis网络库是一个单线程EPOLL模型的网络库,和Memcached使用的libevent相比,它没有那么庞大,代码一共2000多行,因此比较容易分析。本篇拿出了Redis网络部分的代码,添加了应用层buffer,让它现在变成了一个可以实现tcp通信的程序。


Redis网络库是一个单线程EPOLL模型,也就是说接收连接和处理读写请求包括定时器任务都被这一个线程包揽,真的是又当爹又当妈,但是效率一定比多线程差吗?不见得。

单线程的好处有:

1:避免线程切换带来的上下文切换开销。

2:单线程避免了锁的争用。

3:对于一个内存型数据库,如果不考虑数据持久化,也就是读写物理磁盘,不会有阻塞操作,内存操作是非常快的。


#The network library from redis v4.0.9 -- https://github.com/antirez/redis

#把源码以下文件提取出来即可使用,无需作任何修改。

#/redis-unstable/src/ae.c

#/redis-unstable/src/ae.h

#/redis-unstable/src/ae_epoll.c

#/redis-unstable/src/ae_evport.c

#/redis-unstable/src/ae_kqueue.c

#/redis-unstable/src/ae_select.c

#/redis-unstable/src/anet.c

#/redis-unstable/src/anet.h

#/redis-unstable/src/atomicvar.h

#/redis-unstable/src/config.h

#/redis-unstable/src/fmacros.h

#/redis-unstable/src/zmalloc.c

#/redis-unstable/src/zmalloc.h


根据内存分配器的使用不同,区别为:


完整的工程源码下载(malloc使用原生的libc):https://download.csdn.net/download/libaineu2004/10468733


完整的工程源码下载(malloc使用jemalloc):https://download.csdn.net/download/libaineu2004/10468734


如果不清楚libc和jemalloc的概念,请看http://blog.csdn.net/libaineu2004/article/details/79400357


jemalloc的源码下载和编译:https://blog.csdn.net/libaineu2004/article/details/79402103




CMakeLists.txt(使用libc)


cmake_minimum_required(VERSION 2.8)
#The network library from redis v4.0.9 -- https://github.com/antirez/redis
#No changes were made.
#/redis-unstable/src/ae.c
#/redis-unstable/src/ae.h
#/redis-unstable/src/ae_epoll.c
#/redis-unstable/src/ae_evport.c
#/redis-unstable/src/ae_kqueue.c
#/redis-unstable/src/ae_select.c
#/redis-unstable/src/anet.c
#/redis-unstable/src/anet.h
#/redis-unstable/src/atomicvar.h
#/redis-unstable/src/config.h
#/redis-unstable/src/fmacros.h
#/redis-unstable/src/zmalloc.c
#/redis-unstable/src/zmalloc.h
project(myRedisNetDemo)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -g")
set(REDIS_SRC ./redis_network/ae.c ./redis_network/anet.c ./redis_network/zmalloc.c)
include_directories(./redis_network) #https://github.com/antirez/redis
add_executable(${PROJECT_NAME} example_firecat.c buffer.c ${REDIS_SRC})
CMakeLists.txt(使用jemalloc)
cmake_minimum_required(VERSION 2.8)
#The network library from redis v4.0.9 -- https://github.com/antirez/redis
#No changes were made.
#/redis-unstable/src/ae.c
#/redis-unstable/src/ae.h
#/redis-unstable/src/ae_epoll.c
#/redis-unstable/src/ae_evport.c
#/redis-unstable/src/ae_kqueue.c
#/redis-unstable/src/ae_select.c
#/redis-unstable/src/anet.c
#/redis-unstable/src/anet.h
#/redis-unstable/src/atomicvar.h
#/redis-unstable/src/config.h
#/redis-unstable/src/fmacros.h
#/redis-unstable/src/zmalloc.c
#/redis-unstable/src/zmalloc.h
project(myRedisNetDemo)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -g")
set(REDIS_SRC ./redis_network/ae.c ./redis_network/anet.c ./redis_network/zmalloc.c)
find_library(JEMALLOC_LIB libjemalloc.so /usr/local/lib)
IF (NOT JEMALLOC_LIB)
    MESSAGE(FATAL_ERROR "libjemalloc not found")
ENDIF(NOT JEMALLOC_LIB)
SET(JEMALLOC_INCLUDE_DIR /usr/include/jemalloc)
SET(JEMALLOC_LIB /usr/local/lib)
INCLUDE_DIRECTORIES(./redis_network) #https://github.com/antirez/redis
INCLUDE_DIRECTORIES(${JEMALLOC_INCLUDE_DIR})
LINK_DIRECTORIES(${JEMALLOC_LIB})
#ADD_EXECUTABLE必须在TARGET_LINK_LIBRARIES前面,否则会报错
ADD_EXECUTABLE(${PROJECT_NAME} example_firecat.c buffer.c ${REDIS_SRC})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} jemalloc)




buffer.h,关注头文件包含:


#include "zmalloc.h"//libc要用这个
//#include "redis_network/zmalloc.h"//或者libc要用这个
//#include "myjemalloc.h"//jemalloc要用这个
#ifndef MYREDISNET_AEBUFFER_H
#define MYREDISNET_AEBUFFER_H
/// 《Linux多线程服务端编程:使用muduo C++网络库》陈硕著 7.4章节,P204
/// https://github.com/chenshuo/muduo
/// muduo buf:A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
///
/// @code
/// +-------------------+------------------+------------------+
/// | prependable bytes |  readable bytes  |  writable bytes  |
/// |                   |     (CONTENT)    |                  |
/// +-------------------+------------------+------------------+
/// |                   |                  |                  |
/// 0      <=      readerIndex   <=   writerIndex    <=     size
///
/// @endcode
//#include "zmalloc.h"//不能直接包含这个头文件,编译会报错 basic_string.h:2423:7: error: ‘__str’ was not declared in this scope
#include "myjemalloc.h"//要用这个
#include <sys/types.h>
#define DEFAULT_BUFF_SIZE        1024
typedef struct {
    unsigned char *buff;
    size_t size;
    size_t read_idx;
    size_t write_idx;
} buffer_t;
buffer_t *alloc_buffer();
void free_buffer(buffer_t *buffer);
void check_buffer_size(buffer_t *buffer, size_t avlid_size);
size_t get_readable_size(buffer_t *buffer);
size_t get_writeable_size(buffer_t *buffer);
#endif //MYREDISNET_AEBUFFER_H




myjemalloc.h -- 本人自定义的头文件


#ifndef __MYJEMALLOC_H
#define __MYJEMALLOC_H
#include <jemalloc/jemalloc.h>
#define zmalloc(size) je_malloc(size)
#define zcalloc(count,size) je_calloc(count,size)
#define zrealloc(ptr,size) je_realloc(ptr,size)
#define zfree(ptr) je_free(ptr)
#define zmallocx(s
ize,flags) je_mallocx(size,flags)
#define zdallocx(ptr,flags) je_dallocx(ptr,flags)
#endif



buffer.c

#include "buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
buffer_t *alloc_buffer()
{
    buffer_t *buffer = zmalloc(sizeof(buffer_t));
    if (buffer == NULL) {
        goto err;
    }
    buffer->buff = zmalloc(DEFAULT_BUFF_SIZE);
    buffer->size = DEFAULT_BUFF_SIZE;
    buffer->read_idx = 0;
    buffer->write_idx = 0;
    return buffer;
err:
    if (buffer) {
        zfree(buffer->buff);
        buffer->buff = NULL;
        zfree(buffer);
        buffer = NULL;
    }
    return NULL;
}
void free_buffer(buffer_t *buffer)
{
    if (buffer) {
        zfree(buffer->buff);
        buffer->buff = NULL;
        zfree(buffer);
        buffer = NULL;
    }
}
void check_buffer_size(buffer_t *buffer, size_t avlid_size)
{
    if (buffer->read_idx > DEFAULT_BUFF_SIZE) {
        size_t data_len = get_readable_size(buffer);
        memmove(buffer->buff, buffer->buff + buffer->read_idx, data_len);
        buffer->read_idx = 0;
        buffer->write_idx = data_len;
    }
    if (get_writeable_size(buffer) < avlid_size) {
        size_t new_size = buffer->size + avlid_size;
        buffer->buff = zrealloc(buffer->buff, new_size);
        buffer->size = new_size;
    }
}
size_t get_readable_size(buffer_t *buffer)
{
    assert(buffer->size >= buffer->write_idx);
    assert(buffer->read_idx <= buffer->write_idx);
    return buffer->write_idx - buffer->read_idx;
}
size_t get_writeable_size(buffer_t *buffer)
{
    assert(buffer->size >= buffer->write_idx);
    assert(buffer->read_idx <= buffer->write_idx);
    return buffer->size - buffer->write_idx;
}


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
7天前
|
NoSQL Linux 测试技术
Redis的安装(Linux版)
Redis的安装(Linux版)
150 1
|
17天前
|
安全 Linux 虚拟化
网络名称空间在Linux虚拟化技术中的位置
网络名称空间(Network Namespaces)是Linux内核特性之一,提供了隔离网络环境的能力,使得每个网络名称空间都拥有独立的网络设备、IP地址、路由表、端口号范围以及iptables规则等。这一特性在Linux虚拟化技术中占据了核心位置🌟,它不仅为构建轻量级虚拟化解决方案(如容器📦)提供了基础支持,也在传统的虚拟机技术中发挥作用,实现资源隔离和网络虚拟化。
网络名称空间在Linux虚拟化技术中的位置
|
17天前
|
网络协议 安全 Linux
Linux网络名称空间之独立网络资源管理
Linux网络名称空间是一种强大的虚拟化技术🛠️,它允许用户创建隔离的网络环境🌐,每个环境拥有独立的网络资源和配置。这项技术对于云计算☁️、容器化应用📦和网络安全🔒等领域至关重要。本文将详细介绍在Linux网络名称空间中可以拥有的独立网络资源,并指出应用开发人员在使用时应注意的重点。
|
17天前
|
安全 网络协议 Linux
Linux网络名称空间概述
Linux网络名称空间是操作系统级别的一种虚拟化技术🔄,它允许创建隔离的网络环境🌐,使得每个环境拥有自己独立的网络资源,如IP地址📍、路由表🗺️、防火墙规则🔥等。这种技术是Linux内核功能的一部分,为不同的用户空间进程提供了一种创建和使用独立网络协议栈的方式。本文旨在全方面、多维度解释Linux网络名称空间的概念、必要性和作用。
Linux网络名称空间概述
|
17天前
|
NoSQL Linux Redis
linux 下和win下安装redis 并添加开机自启 图文详解
linux 下和win下安装redis 并添加开机自启 图文详解
17 0
|
15天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
39 6
|
5天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
17天前
|
网络协议 Linux
在Linux中,管理和配置网络接口
在Linux中管理网络接口涉及多个命令,如`ifconfig`(在新版本中被`ip`取代)、`ip`(用于网络设备配置)、`nmcli`(NetworkManager的CLI工具)、`nmtui`(文本界面配置)、`route/ip route`(处理路由表)、`netstat/ss`(显示网络状态)和`hostnamectl/systemctl`(主机名和服务管理)。这些命令帮助用户启动接口、设置IP地址、查看连接和路由信息。不同发行版可能有差异,建议参考相应文档。
19 4
|
1天前
|
存储 NoSQL Linux
Redis入门到通关之Redis5种网络模型详解
Redis入门到通关之Redis5种网络模型详解
|
3天前
|
网络协议 Linux Shell
【linux网络(一)】初识网络, 理解四层网络模型
【linux网络(一)】初识网络, 理解四层网络模型