前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单机数据库的实现(下)

单机数据库的实现(下)

作者头像
用户7962184
发布2020-11-20 15:06:51
5170
发布2020-11-20 15:06:51
举报
文章被收录于专栏:没事多喝水没事多喝水

事件

redis服务器是一个事件驱动程序,主要处理两类事件:文件事件和时间事件。

文件事件

文件事件处理器使用I/O多路复用的程序来同时监听多个套接字,虽然redis的文件事件处理器以单线程方式运行,但通过io多路复用监听多个套接字,这样实现了高性能的网络通讯模型,又可以很好地让redis以单线程的方式运行,保持了单线程设计的简单性。(这是redis单线程还能那么快的原因之一)

文件事件的构成

由四个组成部分:套接字,io多路复用程序,文件事件分派器以及事件处理器。

image-20200825161924824

当套接字变得可读(客户端对套接字执行write操作或者执行close操作)的时候,或者有新的可应答套接字出现时,套接字产生AE_READABLE事件。

当套接字变得可写时(客户端对套接字执行read操作),套接字产生AE_WRITABLE事件。

  • 一次完整的连接通讯流程是怎么样子的?

假设一个redis服务器正在运作,这个时候服务器的监听套接字的AE_READABLE事件处于监听情况下。

这时有个redis客户端向服务器发起连接,那么监听套接字将产生AE_READABLE事件,触发连接应答处理器执行。

连接处理器应答之后会创建客户端套接字,客户端状态,并将客户端套接字的AE_READABLE事件与命令请求处理器进行关联。

然后假设客户端向主服务器发送一个命令请求,那么客户端套接字将产生AE_READABLE事件,引发命令请求处理器执行,处理器读取相关的命令内容,传给相关的程序执行。

之后命令会产生相关的恢复,为了将这个回复给客户端,服务器会将客户端套接字的AE_WRITABLE事件与命令回复处理器关联。当客户端尝试读取命令回复的时候,客户端套接字会产生AE_WRITABLE事件,触发命令回复处理器执行,当命令回复处理器将命令回复全部写入到套接字后,服务器就会解除客户端 套接字的事件和关联。

image-20200825182326976

时间事件

redis的时间事件是用周期性事件(让一个程序每隔指定时间就执行一次)

主要有三个属性组成,id(唯一标识号),when(时间事件的到达时间),timeProc(时间事件处理函数)

  • 那具体是怎么实现的?

redis服务器将所有的时间事件都放在一个无序列表中,事件执行器会去遍历这些节点,如果发现时间到达,就会执行对应的时间事件。

  • 这样实现不会很耗费资源吗?

不会 ,因为redis的时间事件很少,正常模式下只有serverCron一个事件。

  • serverCron函数是干嘛的?

主要工作有:

  1. 更新服务器的各类统计消息,比如时间,内存占用,数据库占用等。
  2. 清理数据库中的过期键值对。
  3. 关闭和清理链接失效的客户端。
  4. 尝试进行AOF或RDB持久化操作。
  5. 如果服务器是主服务器,那么对服务器进行定期同步。
  6. 如果处于集群模式,对集群进行定期同步和连接测试。

调度

  • 因为服务器存在文件事件和时间事件,他们是怎么调度执行的?

很简单,ae.c/aeProcessEvents负责,如果有时间事件要处理,就不阻塞去处理时间事件,如果没有时间时间,会阻塞一下,来等待文件事件,然后执行文件事件,执行时间事件,然后不停死循环执行。

客户端

redis保存了客户端当前的状态信息,以及执行相关功能时需要用到的数据结构,其中包括:

  • 客户端的套接字描述符(伪客户端是-1,在aof恢复用到,否则大于1,每个客户端都是唯一的)。
  • 客户端的名字。(通过setname设置)
  • 客户端的标识符。(标识客户端的角色(从服务器,微客户端)和客户端的状态(执行monitor命令等))
  • 客户端正在使用的数据库的指针,已经该数据库的号码。
  • 客户端当前要执行的命令,命令的参数,命令参数的个数,以及指向命令实现函数的指针。(从缓存区分析的到的命令内容)
  • 客户端的输入缓冲区和输出缓冲区。(缓存了客户端的命令以及服务端的输出)
  • 客户端的复制状态信息,以及进行复制所需的数据结构。
  • 客户端执行BRPOP,BLPOP等列表阻塞命令时使用的数据结构。
  • 客户端的事务状态,以及执行WATCH命令时用到的数据结构。
  • 客户端执行发布与订阅功能用到的数据结构。
  • 客户端的身份验证标志。
  • 客户端的创建时间,最后一次通信时间。

是通过链表把多个客户端状态记录到服务器中。

  • 客户端的关闭时机是什么时候?
  1. 客户端退出。
  2. 客户端发送了不符合协议内容的数据。
  3. 服务端调用CLIENT KILL
  4. 服务端设置了timeout配置,那么客户端空转太长就会被关闭。
  5. 客户端的命令大小超过1G。
  6. 输出缓冲区大于限制大小会被关闭。

服务器

命令执行器是如何工作的?

命令执行器首先根据argv[0]的值,在命令表中找到对应的redisCommand对象。

这个对象记录了命令相关的细节,比如允许参数多少,实现函数指针,对该命令的标识符,以及一些统计信息。

image-20200826114220363

服务器先利用这些对命令进行检查,如果检查失败了,则返回一个错误,如果打开了监视器,就会把要执行的命令和参数等消息发给监视器。

检查完毕之后,就调用执行命令的相关函数,得到回复之后会保存在客户端状态的输出缓冲区里面。

执行结束之后还有一些特殊任务,有统计慢查询,修改链接的统计信息,aof写入到AOF缓冲区里面,复制命令到其它从服务器。

最后套接字变为可写状态的时候,把输出缓冲区里面的数据返回给客户端。

  • serverCron函数详细作用?
  1. 更新缓存服务器的lruclock时钟,算每个key的lru值并不是实时的,而是这个值减去每个key的lru的值。
  2. info中的一些统计信息。
  3. 处理sigterm信号,在退出redis之前做相关的操作,比如RDB持久化。
  4. 关闭无用客户端连接。
  5. 抽查部分key,并删除过期的部分key。
  6. 将延迟的FGREWRITEAOF执行。
  7. 将AOF缓冲区的内容写入AOF文件。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

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