前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis代码走读与编程实践——网络交互篇(下)

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

原创
作者头像
王鹏程1990
修改2021-06-19 18:58:38
8310
修改2021-06-19 18:58:38
举报
文章被收录于专栏:源码阅读源码阅读

,导语

在文章《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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ,导语
    • 简单的连接实验
      • 简单的命令交互实验
        • 基于epoll的server demo
        • 参考资料
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档