Redis---c/s端运行流程&事件

一,事件

    Redis是一个事件驱动程序(也就是,请求才会执行操作)那么主要产生的事件是什么呢?下面的两个。

一,文件事件

    服务器和客户端连接交互产生的事件,Redis基于Readcot模式开发了自己的网络事件处理器,使用IO使用多路复用,同时监听多个套接字,也就是连接,绑定事件处理器,当事件到达的时候,调用对应的事件处理器。

    1.文件事件处理器的构成:四个部分:套接字,IO多路复用程序,文件事件派发,事件处理器(可以理解为socket,selector,dispatcher,handler)

    我们可以确定的一点,在多路复用中,对连接事件的读取,肯定是单线程的,然后,多个事件并发到达,它不是使用多线程来处理的,而是通过一个队列存放,一个handler线程来处理所有的事件

    问题:单线程如何保证高并发?

    答案:1.cpu不说redis的瓶颈,内存大小or网络宽带才是瓶颈。内存速度也很快。

               2.不需要锁的消耗,不需要线程切换的消耗。

              3.单线程绷不住了,使用集群的方式解决,使用多线程也也解决不了问题。(多进程)

              4.多路复用技术,事件不会发生等待阻塞。

              5.Hash结构,存储读取速度也比较快。

    参考链接:https://www.jianshu.com/p/0bf46dd0aaf5

2.事件的类型:请求连接,关闭,可读,可写事件,同一个socket产生两个事件的时候,优先考虑可读事件。

3.文件事件的处理器

  •  连接应答处理器:acceptTcphandler函数,在redis初始化的时候,要把这个处理器绑定到accept事件中。
  •  命令请求处理器:readQueryFromClient,包装read,负责套接字中读入客户端发送的命令,
  •  命令回复处理器:sendReplyToClient,包装是write,服务器向客户端发送命令回复。

(注意这的read和write不是针对数据库的,而是针对服务端套接字的,c发送过来s就去读,s发送给c就是写)

有没有一点像tcp三次握手。
 
 

二,时间事件

分类

    1.定时事件:在指定的事件执行,比如30秒之后。

    2.周期性事件:隔一段事件执行一次,比如30秒执行一次(两种没什么好区分的,根据业务玩就是了)

时间事件的三个属性组成

    id:服务器为时间事件创建的全局唯一ID,递增。

    when:unix时间戳。记录了事件到达的时间。(定时持久化)

    timeProc:时间事件处理器,一个函数(和上面的文件处理器一个道理,知不道文件处理器是绑定事件,时间处理器是绑定时间)

实现:服务器将所有的时间都保存在一个无序链表中(看来就是一个结构体指针),时间执行器遍历观察它的时间是否已经到达,然后执行(这个和键的过期删除极其相似),这个周期时间和定时时间就看函数的返回值,定时的返回值收到就会进行删除这个事件。这里的无序不是值ID乱序,而是指when时间的乱序的,所以执行的时候要进行遍历。

 

三,事件的调度与执行

    因为redis是单线程的,而且文件事件和时间事件是同时存在的,所以需要调度配合,做好处理。

    整体思路:计算时间到达的时间事件,然后保存起来,在规定的阻塞事件中,等待文件事件的产生,然后执行在这个范围内的文件事件,处理完毕再处理时间事件(那么这里你就会发现,时间事件并不是准时执行的,还需要等待调度)

    

    这里有一个问题,文件事件的处理不是派发的吗,为什么又变成了轮询了,这里是放在队列里面,进行等待。这里就有阻塞了。

 
 
 
 

二,客户端

    Redis是典型的一对多服务器,一个服务器可以和多个客户端相连,多个socket这个可以理解。   服务器使用一个链表来保存客户端,clients:redisClient->redisClient。一个节点就是一个客户但。

  1.属性

  • 套接字描述符:int fd;根据客户端的不同值不同,伪客户端fd=-1,普通客户端>-1,相当于id吧。
  • 名字:默认的客户端没有名字,但是可以设置名字
  • 标志:记录客户端的角色,int flags;比如主从复制里面,有主服务器的客户端,从服务客户端。还有很多标识,比如正在阻塞等等。
  • 输入缓冲区:用于保存客户端发送的命令,sds querybuf;输入缓冲区会根据输入的内容动态缩小或者扩大,最大大小不能超过1G,否者会关闭这个客户端。
  • 命令和命令参数:(我们根据socket通信知道,接收端的socket在用户那里有一份,在服务器接通了之后,也会有一份)当服务器收到命令之后,会进行解析,然后把解析及结果:命令参数和命令参数的个数存入客户端的argv属性中和argc属性中,
  • 命令的实现函数:服务之根据argv[0]的值,在命令表中查找对应的命令实现函数(也就是处理函数),这个命令表就是一个字典,键就是字符串命令,值是redisCommand结构,它存放了对应的处理函数。找到了这个结构,redisClient里面有一个属性就会保存这个结构的指针,方便调用。
  • 输出缓冲区:每个客户端有两个缓冲区,一个是大小固定的,另外一个是可变的,固定的保存比较小的回复,反知,可变的保存比较大的回复。固定的实现是一个char,这里没有使用sds,可变的是用链表实现的。
  • 身份验证:int authenticated 值为0,标识未通过验证,命令会被拒绝,值为1就正常。
  • 时间:记录连接时间,最后一次交互时间,

    2.客户端的创建和关闭

        创建普通客户端:客户端连接到服务器的时候,服务器监听到这个连接事件,就会调用连接事件处理器,为客户端创建相应的客户端状态,并计入到服务器状态结构clients链表的尾部。

        关闭客户端:关闭的原因有多种,进程退出,被杀死,客户端发送了非法命令,客户端主动关闭,时间到达关闭,缓冲区溢出,特别要注意缓冲区的大小是否装得下内容。

 

 

 

三,服务端

    1.命令请求的执行过程

        发送命令请求:用户输入一个请求,户端将请求转换为协议,然后发送给服务器;demo:输入 set key value 客户端转换为:

        读取命令请求:服务器收到命令,保存到客户端状态 的输入缓冲区中,对输入缓冲区的命令进行分析,提取出命令请求中包含的命令参数,以及参数个数u,保存到客户端状态的argv,argc中。调用命令执行器。

        命令执行器

  • 查找命令实现:根据agrv[0]找到命令的实现函数,将指针转给 客户端状态的cmd属性。
  • 执行预备操作:检查之前的操作是否出错(cmd是否为空,参数个数是否完整,身份验证是否Ok,订阅功能如果开启是否正常,服务器是否在载入数据,是否阻塞,是否执行事务)如果是集群版本的,预备操作更加的复杂。
  • 调用命令的实现函数:调用函数,产生相应的回复,把回复保存到客户端状态的输出缓冲区中,
  • 执行后续工作:如果开启了慢查询,添加日志。如果命令耗费时间长,则需要更新计数器。如果开启了AOF,则需要切入aof缓冲区。

        将命令回复发送给客户端:回复以及到了输出缓冲区,关联回复处理器,将客户端套接字改为可写状态,执行回复处理器。

        客户端接收并打印命令回复:客户端收到回复,进行协议转换,展示给用户

    2.serverCron函数

        更新服务器时间缓冲:避免多次调用系统时间函数,保存了系统时间,有秒级别和毫秒级别的时间戳。

        更新LRU时钟:也是时间缓冲的一种

        更新服务器每秒执行命令次数:抽样计算的方式,估算并记录服务器最近一秒钟处理的命令请求数量

        更新服务器内存峰值记录:记录最大的内存使用大小。

        处理SIGTERM信号

        管理客户端资源

        管理数据库资源

        执行被延迟的bg rewrite aof

        检查持久化操作的运行状态

        将AOF缓冲区的内容写入AOF文件

        关闭异步客户端

        增加crionloops计数器的值

    3.初始化服务器

        初始化服务器状态结构:创建redisServer结构,作为服务器的实例,设置默认值,初始化initServerConfig函数()完成,包含了运行id,配置文件路径,端口号,持久化方式,初始化LRU时钟,创建命令表。

        载入配置选项

        初始化服务器数据结构

        还原数据库状态

        执行事件循环:这里就正常工作了。

 
 
参考:《Redis设计与实现》
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值