一、执行流程
每个客户端通过网络连接到redis时,redis将调用函数createClient()为该连接创建一个客户端结构体redisClient,以便保存该客户端的所有信息,该新连接即为业务连接,其主要用于客户端与redis之间的实际数据通信。Redis在createClient()函数中将为连接设置处理函数readQueryFromClient(),也即业务连接上有数据到来时将调用此函数进行处理。
1、redis接受客户端的连接
(1)、redis启动时将调用initServer()函数,调用函数anetTcpServer创建redis的监听socket,所有客户端对redis的网络连接都连接到该socket所监听的端口上;
(2)、调用函数aeCreateFileEvent设置监听socket的处理函数:acceptTcpHandler(),也就是当redis的监听socket收到数据(有新的连接到来)时将调用该函数进行处理;
(3)、lacceptTcpHandler()中将首先调用函数anetTcpAccept为新进来的业务连接创建一个业务socket;该业务socket后续将完成客户端与服务器之间所有的业务数据传输;然后通过函数acceptCommonHandler()调用createClient()为新连接创建一个客户端结构体redisClient.
(4)、在函数createClient()中,将调用函数aeCreateFileEvent设置该客户端的业务数据处理函数readQueryFromClient,即,当该客户端的业务socket中有数据到来了,则调用readQueryFromClient进行处理。
![image.png](https://static.studygolang.com/180905/44f4a849ad24df50f01ed34ce6835c5b.png)
2、redis接受命令处理流程
(1)、客户端的请求数据由网络传递到redis的业务socket,redis将调用函数readQueryFromClient()读取数据到redisClient结构体的接收缓存querybuf中。
(2)、readQueryFromClient()将调用processInputBuffer()对该客户端输入缓存中的数据进行处理。
(3)、函数processInputBuffer()中,将首先解析收到的客户端数据,此解析过程将通过调用函数processInlineBuffer()或processMultibulkBuffer()完成,此过程将解析出客户端的命令名称,命令的参数个数以及具体参数值,redis有其自己定义的通信协议,只需按照此协议即可完成命令解析,其过程可参考本文最后的“附1. redis命令解析”。
(4)、函数processInputBuffer()中,命令解析完成之后将调用函数processCommand()完成命令处理过程。
(5)、将根据命令的名字查找相应的处理函数,命令的名字由前面的命令解析过程确定,命令查询操作将通过函数lookupCommand()完成,此函数将查找server的命令字典以快速找到对应的命令执行函数,查找到命令执行函数之后,还需调用call()函数来具体执行相应的“命令执行函数”。
![image.png](https://static.studygolang.com/180905/266fd16d499769c30d656f83dc3eb9db.png)
二、 3.0集群
Redis 3.0集群采用了P2P的模式,完全去中心化。
1、redis有16384个hash槽;
2、每个node节点分管不同的hash槽;
3、集群中的所有信息(节点、端口、slot等),通过节点之间定期的数据交换而更新,PING-PONG机制;
Redis 3.0集群的工作流程如下图所示
![image.png](https://static.studygolang.com/180905/d4c50f43ebb71f6b475ed4bb17dc7806.png)
三、哨兵机制
一个一主多从的Redis系统中,可以使用多个哨兵进行监控任务以保证系统足够稳健。此时,不仅哨兵会同时监控主数据库和从数据库,哨兵之间也会相互监控。并且使用奇数个哨兵。
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
(1)、监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
(2)、提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
(3)、自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。
哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master.
四、内部数据结构
1、 有序集合跳跃表实现 ???? https://blog.csdn.net/lz710117239/article/details/78408919
![image.png](https://static.studygolang.com/180906/662f59f1a0cabc8ce66ebddea0d2518a.png)
随机算法
int zslRandomLevel(void) {
int level = 1;
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
该算法的核心条件:(random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF), random()&0xFFFF形成的数,均匀分布在区间[0,0xFFFF]上,那么这个数小于(ZSKIPLIST_P * 0xFFFF)的概率是ZSKIPLIST_P
redi运用场景小结:
1、string:
(1)、计数器运用、缓存
(2)、位操作(大数据处理),几亿用户系统的签到、在线状态
2、list:
(1)、最新N个数据的操作
(2)、消息队列
(3)、删除和过滤
(4)、分析分析,用于数据统计与防止垃圾邮件(结合set)
3、set
(1)、数据排重、统计
(2)、实时系统、发垃圾系统
(3)、共同好友、二度好友
(4)、求交集,实现好友推荐
4、hash
(1)、用户信息存储
5、Sorted Set:
(1)、排行榜,TOP N
(2)、设定精准过期时间、时间戳作为score
有疑问加站长微信联系(非本文作者))