0%

其实在6.0之前,redis也是有多线程的,BIO这个模块就是使用多线程处理关闭文件刷新aof数据到磁盘惰性释放key这三件事情。在6.0版本中,redis引入的多线程,只是用来处理跟客户端的网络I/O,这里的多线程同时只在做一件事,只可能同时在读数据,或者同时在写。不会出现,一部分线程读数据一部分写数据的情况。

多线程仅仅是用在网络I/O这块,在执行命令阶段,还是跟之前一样,由主进程依次执行。在一个处理周期内,主线程把有读数据需求的客户端,平均分配到每个子线程的待处理池。然后打开开关,并设置此阶段所有线程的行为为读操作,之后所有线程开始读取数据,主线程会一直等到所有的子线程都处理完,然后在主线程中依次解析&执行命令。然后主线程把有写数据需求的客户端平均分配到每个子线程的待处理池,打开开关,并设置此阶段所有线程的操作行为为写操作,之后所有线程开始执行写数据。

上述是大概的多线程流程,实际情况下,并不是每一个处理周期都会用到多线程来处理网络I/O,详细的会在下面介绍。

redis多线程为什么只在网络I/O这块,因为redis的一个核心就是处理命令的时候,使用单线程处理,这样做避免了资源的竞争问题。如果执行命令的过程中改成多线程的话,则需要对大量的资源进行加锁来保证,这样对于redis来说改动是很大的,从DB,到里面的每一个key、value,再到每一个value的数据结构实现,都是需要考虑并发的问题的。

阅读全文 »

redis集群是由多个节点实例组成的网状拓扑结构,每一个节点有两个对外服务的端口,一个是面向普通客户端的正常服务(默认端口是6379),另一个则是用于集群内节点交流的服务(默认端口是6379+10000),主要包括增加节点、删除节点、分配哈希槽点、迁移槽点、故障修复等功能。集群的实现和哨兵的实现有相同的地方,也有不一样的地方。相同点是二者都支持主从模式,并且在master挂掉之后,能够自动发现并修复。不一样的地方是哨兵模式下的故障修复是从哨兵中选出一个leader,参与投票的也是哨兵节点,然后由leader哨兵主导完成整个修复过程。在集群模式下,则不存在哨兵这样的领导层角色节点,故障修复过程则是由挂掉master下的slave节点发起,其余master参与投票来选出一个slave来主导修复过程。

redis集群的实现引入了哈希槽的概念,将整个集群分为16384个槽点,集群中每个节点负责其中的一部分。通过对命令中key进行运算,结果对总的槽点取余来决定应该访问哪个槽点。当集群稳定后,集群中每个槽点都会有一份完整的槽点路由表,记录每个槽点应该去哪个节点。

阅读全文 »

为了提高redis服务的高可用性,redis提供了一个哨兵模式。在该模式下,哨兵会做以下三件事:

  1. 监控master节点和slave节点的运行情况;
  2. 当某个节点出现异常时,通知告警当前情况;
  3. 当master节点发生故障时,哨兵会从slave节点中挑选一个节点成为新的master,并通知其他的slave节点将服务器配置改为新的master,当客户端尝试连接原来的master时,会向客户端返回新的master地址。当运行哨兵模式的时候,都是多个哨兵一起运行,否则哨兵只能提供监控&告警的功能,故障修复功能则永远不会触发。
阅读全文 »

redis的发布订阅功能很简单,消息的生产方不直接和订阅方交互,而是通过channel渠道,和KAFKA中的topic是同样的角色。

订阅分为两种类型,一种是具体的,指定了channel的名字,比如hello;另一种是模糊的,指定的channel名字是含有正则的,如hell*。每一个client有两个属性,分别存储自己订阅的具体channel,和模糊的channel。server也有两个字段,维护了所有的channel及被订阅的client,和所有的模糊channel。

当有客户端往某个channel中发送消息时,server会有两步操作。1.向这个channel对应的所有的client发送消息;2.依次遍历所有的模糊channel,如果模糊的channel和改channel匹配的话,则向对应的client发送消息。如果一个客户端订阅了多个模糊channel,且都命中,则会收到两个消息。

当客户端正常取消订阅的时候,就从client和server对应的列表中移除。当客户端没有取消订阅就退出时,定时任务检测到客户端超时后,释放客户端时,会主动释放客户端所有的订阅。

阅读全文 »

集合作为redis中的一种常用的数据结构,根据其集合内的元素特点,底层采用数组哈希表两种方式进行实现。集合初始化的时候,会先根据的第一个元素是否能够转化成整形,然后决定使用数组还是哈希表来实现。哈希表是通用的实现方式,数组只是针对所有的元素都是整数的情况。在一定的情况下,会发生转换,转换是单向的,只能从数组转到到哈希表。触发的条件有两个,在数组实现的基础上,一是往集合内加入非整数元素,二是集合的大小超过了限制(默认是512,可以通过参数set-max-intset-entries修改)。这是因为数组的实现的集合,在每次新增、删除操作的时候,都会重新去申请内存,当涉及到的内存比较大的时候,效率会有所降低。

阅读全文 »

redis支持5中数据结构,分别是字符串、列表、集合、有序集合以及哈希表。在不同的场景使用合适的数据结构,会节省很多精力。

阅读全文 »

为提升redis的性能,从实例的数量上来解决这个问题,可以使用redis的主从同步功能。可以在启动前预先配置拓扑结构,也可以在运行中动态改变拓扑结构。redis主从同步的命令主要有两个sync和psync。psync是sync的升级版本,具有断开续传的特点,解决了sync只能全量更新的问题。

阅读全文 »

rdb作为redis的另一种数据持久化方式,其用途有两种。1、数据持久化,把数据存放到磁盘上。2、主从数据同步,当第一次同步或者从节点同步的信息不在主节点的缓冲区内时,会生成一个rdb文件,然后同步给从节点用于生成初始数据集。

阅读全文 »

概述

rio是redis实现的一个流式I/O抽象,针对不同的输入/输出(文件、内存、fd),提供统一的读、写、查看offset等方法,在aofrdb经常用到文件类型和内存内类。

阅读全文 »

概述

aof是redis数据的一种持久化方式,本质是记录服务器处理的每一个写操作,使用redis协议进行追加存储。当redis重启时,通过还原操作,重建数据集。aof分为两个阶段,一是正常的操作追加;另一种则是aof重写。

阅读全文 »