![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Redis 实现
Redis实现
槑!
这个作者很懒,什么都没留下…
展开
-
【Redis实现系列】事务功能实现
事务实现原理一个事务从开始到结束通常会经历以下三个阶段:事务开始。命令入队。事务执行。事务开始MULTI命令的执行标志着事务的开始:redis> MULTIOKMULTI命令可以将执行该命令的客户端从非事务状态切换至事务状态,这一切换是通过在客户端状态的flags属性中打开REDIS_MULTI标识来完成的,MULTI命令的实现可以用以下伪代码来表示:def MULTI(): # 打开事务标识 client.flags |= REDIS_MULT原创 2020-11-13 00:19:23 · 1407 阅读 · 0 评论 -
【Redis实现系列】监视器实现
监视器通过执行MONITOR命令,客户端可以将自己变为一个监视器,实时地接收并打印出服务器当前处理的命令请求的相关信息每当一个客户端向服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将关于这条命令请求的信息发送给所有监视器redis> MONITOROK1378822099.421623 [0 127.0.0.1:56604] "PING"1378822105.089572 [0 127.0.0.1:56604] "SET" "msg" "hello world"13原创 2020-11-13 00:19:08 · 195 阅读 · 0 评论 -
【Redis实现系列】慢查询日志实现
慢查询日志Redis的慢查询日志功能用于记录执行时间超过给定时长的命令请求,用户可以通过这个功能产生的日志来监视和优化查询速度。服务器配置有两个和慢查询日志相关的选项:slowlog-log-slower-than 选项指定执行时间超过多少微秒(1秒等于1 000 000微秒)的命令请求会被记录到日志上。slowlog-max-len选项指定服务器最多保存多少条慢查询日志。 服务器使用先进先出的方式保存多条慢查询日志,当服务器存储的慢查询日志数量等于slowlog-max-len选项的值时,原创 2020-11-13 00:18:56 · 215 阅读 · 0 评论 -
【Redis实现系列】发布订阅实现
发布订阅频道的订阅与退订当一个客户端执行SUBSCRIBE命令订阅某个或某些频道的时候,这个客户端与被订阅频道之间就建立起了一种订阅关系。Redis将所有频道的订阅关系都保存在服务器状态的pubsub_channels字典里面,这个字典的键是某个被订阅的频道,而键的值则是一个链表,链表里面记录了所有订阅这个频道的客户端:struct redisServer { // ... // 保存所有频道的订阅关系 dict *pubsub_channels; // ...};SUBSC原创 2020-11-13 00:18:44 · 283 阅读 · 0 评论 -
【Redis实现系列】通知功能实现
通知订阅命令这个功能可以让客户端通过订阅给定的"键空间"或者”事件“,来获知数据库中键的变化,以及数据库中命令的执行情况。订阅键空间通知:SUBSCRIBE _ _keyspace@<dbid>_ _:<keyname>订阅键事件通知:SUBSCRIBE _ _keyevent@<dbid>_ _:<eventname>注意:服务器配置的 notify-keyspace-events 选项决定了服务器允许发送哪类通知想让服务器发送所有类型的 键原创 2020-11-12 00:14:16 · 687 阅读 · 0 评论 -
【Redis实现系列】集群MOVED错误与ASK错误
键操作与Moved错误在对数据库中的16384个槽都进行了指派之后,集群就会进入上线状态,这时客户端就可以向集群中的节点发送数据命令了。实现原理当客户端向节点发送与数据库键有关的命令时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己:如果键所在的槽正好就指派给了当前节点,那么节点直接执行这个命令。如果键所在的槽并没有指派给当前节点,那么节点会向客户端返回一个MOVED错误,指引客户端转向(redirect)至正确的节点,并再次发送之前想要执行的命令。原创 2020-11-12 00:13:44 · 2939 阅读 · 0 评论 -
【Redis实现系列】集群内部消息
集群内部消息集群中的各个节点通过发送和接收消息(message)来进行通信,我们称发送消息的节点为发送者(sender),接收消息的节点为接收者(receiver)节点发送的消息主要有以下五种:MEET消息:当发送者接到客户端发送的CLUSTER MEET命令时,发送者会向接收者发送MEET消息,请求接收者加入到发送者当前所处的集群里面。PING消息:集群里的每个节点默认每隔一秒钟就会从已知节点列表中随机选出五个节点,然后对这五个节点中最长时间没有发送过PING消息的节点发送PING消息,以原创 2020-11-12 00:14:01 · 223 阅读 · 0 评论 -
【Redis实现系列】集群实现与故障迁移
集群节点与槽指派启动集群节点一个节点就是一个运行在集群模式下的Redis服务器,Redis服务器在启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式节点(运行在集群模式下的Redis服务器)会继续使用所有在单机模式中使用的服务器组件,比如说:节点会继续使用文件事件处理器来处理命令请求和返回命令回复。节点会继续使用时间事件处理器来执行serverCron函数,而serverCron函数又会调用集群模式特有的clusterCron函数。cluste原创 2020-11-12 00:13:31 · 258 阅读 · 0 评论 -
【Redis实现系列】Sentinel自动故障转移
故障转移主观下线状态在默认情况下,Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他Sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。实例对PING命令的回复可以分为以下两种情况:有效回复:实例返回+PONG、-LOADING、-MASTERDOWN三种回复的其中一种。无效回复:实例返回除+PONG、-LOADING、-MASTERDOWN三种回复之外的其他回复,或者在指定时限内没有返回任何回复。原创 2020-11-12 00:13:19 · 612 阅读 · 0 评论 -
【Redis实现系列】哨兵Sentinel实现
SentinelSentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。示例:Sentinel系统监视服务器:双环图案表示的是当前的主服务器ser原创 2020-11-12 00:13:04 · 215 阅读 · 0 评论 -
【Redis实现系列】主从复制步骤
主从复制步骤设置主服务器地址和端口当客户端向从服务器发送以下命令时:127.0.0.1:12345> SLAVEOF 127.0.0.1 6379OK从服务器首先要做的就是将客户端给定的主服务器IP地址127.0.0.1以及端口6379保存到服务器状态的masterhost属性和masterport属性里面:struct redisServer { // ... // 主服务器的地址 char *masterhost; // 主服务器的端口 int原创 2020-11-12 00:12:33 · 148 阅读 · 0 评论 -
【Redis实现系列】主从复制实现
主从复制在Redis中,用户可以通过执行 SLAVEOF 命令或者设置 slaveof 选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave)。Redis的复制功能分为同步(sync)和命令传播(command propagate)两个操作:同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库原创 2020-11-12 00:12:19 · 206 阅读 · 2 评论 -
【Redis实现系列】持久化AOF实现
AOF除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的,因为Redis的命令请求协议是纯文本格式。示例redis> SET msg "hello"OKredis> SADD fruits "apple" "banana" "cherry"(integer) 3redis> RPUSH numbers 128 256 512(integer) 3原创 2020-11-12 00:12:08 · 162 阅读 · 0 评论 -
【Redis实现系列】持久化RDB实现
RDBRDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。创建与载入创建有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE。SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求:redis> SAVE原创 2020-11-12 00:11:55 · 240 阅读 · 0 评论 -
【Redis实现系列】过期键处理
过期键处理过期键的判定通过过期字典,程序可以用以下步骤检查一个给定键是否过期:检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间。检查当前UNIX时间戳是否大于键的过期时间:如果是的话,那么键已经过期;否则的话,键未过期。伪代码描述def is_expired(key): # 取得键的过期时间 expire_time_in_ms = redisDb.expires.get(key) # 键没有设置过期时间 if expire原创 2020-11-11 22:38:34 · 835 阅读 · 0 评论 -
【Redis实现系列】RedisDB实现
RedisDB核心实现概述Redis 服务器将所有数据库都保存在服务器状态 redis.h/redisServer 结构的 db 数组中,db 数组的每个项都是一个 redis.h/redisDb 结构,每个redisDb结构代表一个数据库。定义:struct redisServer { // ... // 一个数组,保存着服务器中的所有数据库 redisDb *db; // 初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少原创 2020-11-11 22:38:23 · 1322 阅读 · 1 评论 -
【Redis实现系列】RedisClient实现
RedisClientRedis服务器是典型的一对多服务器程序一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复。通过使用由I/O多路复用技术实现的文件事件处理器,Redis服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信。核心实现概述对于每个与服务器进行连接的客户端,服务器都为这些客户端建立了相应的 redis.h/redisClient结构(客户端状态),这个结构保存了原创 2020-11-11 22:37:58 · 3297 阅读 · 0 评论 -
【Redis实现系列】初始化服务器
初始化服务器初始化状态结构初始化服务器的第一步就是创建一个struct redisServer类型的实例变量server作为服务器的状态,并为结构中的各个属性设置默认值。初始化server变量的工作由redis.c/initServerConfig函数完成,以下是这个函数最开头的一部分代码:void initServerConfig(void){ // 设置服务器的运行id getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE);原创 2020-11-11 22:37:46 · 236 阅读 · 0 评论 -
【Redis实现系列】RedisServer实现
RedisServer请求处理 (文件事件)命令请求执行过程:即 processFileEvents 里读事件处理器的主要操作发送命令请求Redis服务器的命令请求来自Redis客户端,当用户在客户端中键入一个命令请求时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器。示例(步骤一):SET KEY VALUE# 那么客户端会将这个命令转换成协议:*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALU原创 2020-11-11 22:37:30 · 1144 阅读 · 0 评论 -
【Redis实现系列】事件驱动模型实现
事件模型Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件:文件事件(file event):Redis服务器通过套接字(socket)与客户端(或者其他Redis服务器)进行连接,而文件事件就是服务器对套接字(socket)操作的抽象。服务器与客户端(或者其他服务器)的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完成一系列网络通信操作。时间事件(time event):Redis服务器中的一些操作(比如serverCron函数)需要在给定的时间点执行,而时间事件就原创 2020-11-11 22:37:16 · 230 阅读 · 0 评论 -
【Redis实现系列】五种基本类型对象实现
字符串对象字符串对象的编码可以是int、raw或者embstr注意:listnode#value、dictEntry#key、zskipListnode#obj,里面的值对象都是字符串对象(即 redisObject 且 type = string)。字符串对象是Redis五种类型的对象中唯一一种会被其他四种类型对象嵌套的对象。下面示例图片里的 “StringObject" 就是 redisObject 的 String 类型embstrembstr编码是专门用于保存短字符串的一种优化原创 2020-11-11 22:36:55 · 1290 阅读 · 0 评论 -
【Redis实现系列】RedisObject实现
RedisObjectRedis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。Redis 数据库中的每个键值对的键和值都是一个对象 redisObject。typedef struct redisObject { // 类型(共有 5 种:string、list、hash、set、zset) unsigned type:4; // 编码(共有原创 2020-11-11 22:36:40 · 357 阅读 · 0 评论 -
【Redis实现系列】双端链表、字典、跳表
双端链表链表在Redis中的应用非常广泛,比如列表键(lpush、rpush)的底层实现之一就是链表。当一个列表键包含了数量比较多的元素,又或者列表中包含的元素都是比较长的字符串时,Redis就会使用链表作为列表键的底层实现。除了链表键之外,发布与订阅、慢查询、监视器等功能也用到了链表,Redis服务器本身还使用链表来保存多个客户端的状态信息,以及使用链表来构建客户端输出缓冲区(output buffer)实现链表节点:adlist.h/listNode(双端链表)typedef原创 2020-11-11 22:36:16 · 300 阅读 · 0 评论 -
【Redis实现系列】SDS、整数集合、压缩列表
数据结构SDS 动态字符串在Redis里面,C字符串只会作为字符串字面量(string literal)用在一些无须对字符串值进行修改的地方,比如打印日志。当Redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,Redis就会使用SDS来表示字符串值Redis的数据库里面,包含字符串值的键值对在底层都是由SDS实现的。除了用来保存数据库中的字符串值之外,SDS还被用作缓冲区(buffer):AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区,都是由SDS实现的。原创 2020-11-11 22:36:01 · 303 阅读 · 0 评论