redis代码走读与编程实践——网络交互篇(下)

导语

在文章《redis代码走读与编程实践——网络交互篇(上)》中,对redis连接请求与建立流程进行源码剖析和走读;本文主要尝试编写一个简单的redis客户端和redis-server进行连接和交互,借此加深对上文源码走读的理解。为便于理解和组织文章,实验分为三个部分:

连接建立实验。

命令交互实验。

模拟redis机制实现的简单server的demo。

简单的连接实验

本实验通过简单的单线程的同步交互方式,与redis-server建立连接;过程不涉及redis的命令交互,同时验证redis的最大连接和保护模式配置。

所谓最大连接配置,是指redis支持配置最大连接数,当连接数达到最大连接数时,不再接收新的连接请求;对应配置文件的maxclients配置项。

所谓保护模式配置,是一种保护机制,当保护模式开启时,若是redis-server没有配置密码,则只接收本机IP地址的连接请求,即127.0.0.1的源IP连接请求。

实验源码如下:

最大链接配置如下:

配置最大连接数为1当同时打开两个客户端,后入的客户端运行之后报错:

对应源码:

保护模式配置如下:

对于开启保护模式,不配置密码的场景下;使用客户端直接链接上去,服务端返回错误信息为为:

验证之前的说明,开启保护模式下,若不配置密码,为了避免redis-server暴露在外网环境下,只允许本机连接;对应源码:

简单的命令交互实验

前文在走读redis源码,我们可以分析出客户端请求redis的源码格式,以set指令为例,我们输入set aaa bbb的时候,实际客户端发给服务器的命令内容为:*3\r\n$3\r\nset\r\n$3\r\naaa\r\n$4\r\nbbb\r\n;其中:

  1. *,是普通指令标识
  2. 3,是参数个数
  3. \r\n是分隔符
  4. $3是字符串长度

源码如下所示:

运行结果:

可见数据是成功写入到redis服务器端了

前文说到,redis协议规定,bulk之间使用\r\n进行分割,但是在代码中没有作相应的校验,只是单取\r进行分割,为了验证这个问题,我们将代码中的\n替换为\t如下图所示:

重新编译,运行,结果如下:

是成功的,说明是可以正常写入的。

需要说明的是,这个客户端只针对set命令做了简单的实现,没有实现解码的部分;所以是一个演示功能代码。

基于epoll的server demo

学习源码,不仅是去看开源项目底层的具体实现;更重要是是学习开源项目优秀的设计思想,为后续的项目开发助力;redis网络交互模块是基于epoll机制实现的连接管理,在本节我们模仿redis-server的连接管理机制,实现一个简易的多链接服务器。

首先简单介绍一下epoll:

众所周知,epoll相对于select,能处理更多的连接并且提供更高的性能;具体是通过以下几点做到的:

  1. epoll需要关注的fds,是通过mmap存放在内核态与用户态都可见的位置,避免了epoll-wait时用户态和内核态之间的内存拷贝;
  2. epoll底层使用红黑树管理fds列表,相比于顺序查询提供了更高的增删查改的性能;
  3. epoll-wait返回的是已经就绪的fds列表,主调接口不必遍历所有的fd收集事件;
  4. epoll-wait在收集已经就绪的fd列表的时候,也不是遍历监控的fd,而是让已经就绪的fd自己插入到就绪列表,减少了无意义的遍历行为;

介绍完epoll的原理,server-demo源码如下:

主要包括以下几点:

  1. aeEventElem:用于描述所有被监控的fd,包括关注的事件(mask)、对应的回调(rfunc/wfunc)、以及连接对应的session数据(privdata)
  2. aeEventPool:用于管理所有的需要监控的FD(eventList),fd的值作为eventlist的下标
  3. 接口:aeAddFileEvent用于注册fd事件被触发时的的回调
  4. 因此,主流程里面,首先创建epoll实例,然后创建监听socket,将监听socket事件被触发的回调aeAcceptSocket通过adAddFileEvent注册到aeEventPool中&通过epoll_ctl注册到epoll实例中;然后轮询调用epoll_wait,若有事件发生,被触发的事件存放在events数组中,我们通过event的fd找到对应回调;若是监听接口,则分配连接,并注册连接回调;若是其他接口,则直接读取数据即可

参考资料

1. https://redis.io/

2. https://www.xilidou.com/2018/03/22/redis-event/

3. https://www.runoob.com/redis/redis-pipelining.html

4. https://cloud.tencent.com/developer/article/1005481

5. http://blog.chinaunix.net/uid-28541347-id-4238524.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券