《redis 设计与实现》这本书写的非常好,它先介绍了redis中使用的一些数据结构(数据结构是用来实现各种对象的)。 一种对象(比如string)在不同场景下,可能是由多种数据结构实现的。数据结构包括:

  • 简单动态字符串(simple dynamic string, sds),用来实现string

  • 链表,用来实现列表(list)。当列表中包含了较多的元素,或者每一个元素都是比较长的字符串时,redis就会采用链表作为list的实现

  • 字典,用来实现hash。当一个hash中包含的键值对数目比较多,或者键值对中的元素都是比较长的字符串时,redis就会采用字典来 实现hash;此外,redis的数据库也是使用字典来实现的,对数据库的增删改查操作就是在操作字典。

  • 跳跃表(skiplist)。它是一种有序的数据结构。用来实现zset(有序集合),如果一个有序集合包含的元素比较多,或者有 序集合中的每个元素都是比较长的字符串时,就会采用跳表来实现。

  • 整数集合(intset)。用来实现集合(set),当一个集合中只包含整数值元素,并且包含的数目不多时,redis就会采用intset来 实现集合。

  • 压缩列表(ziplist)。用来实现list或者hash:当一个list中只包含少量元素,并且每个元素都是较短的字符串或者小整数(对比 链表部分),redis就会采用ziplist来实现list;当一个hash中只包含少量键值对,并且每个键值对的键和值都是较短的字符串或 者小整数时(对比字典部分),redis就会采用ziplist来实现hash。

关于redis的各个对象:

  • 字符串:字符串对象的编码方式可以是int(如果值是整数,且可以用long表示)、embstr(长度<=32字节)、raw(大于32字节)

  • 列表:ziplist或者链表

  • 有序集合:可以用ziplist或者skiplist来实现。记住ziplist都是适用于小数据集场景即可;而对于使用skip list来实现 有序集合的功能,本质上是通过一个zset的数据结构来实现的,它包括一个skip list和一个字典dict。跳表用来快速实现 范围查找的功能,字典用来实现获取某一个值的score的功能。必须结合两者的特点才能同时实现这些功能。

redis使用引用计数来实现内存回收的。每个redisObject结构都有一个refcount属性,记录当前对象的引用计数。这个refcount还 带有对象共享的作用。Redis只对包含整数值的字符串对象进行共享。

redis的过期策略:两者相结合 1、惰性删除策略(也就是key被访问时,从过期字典(和真正的数据字典平级)中查找key是否过期),如果是则从数据 字典中删除。

2、定期删除策略:activeExpireCycle函数,会被周期性的调用,它是随机地从过期字典中检查一部分key的过期时间,并删除其中 过期的key。也就是类似采样的策略。随着activeExpireCycle函数的不断执行,服务器中的所有数据库都会被检查一遍,这时函数 将current_db变量重置为0,然后再次开始新一轮的检查工作。

需要注意的是:通常我们运行在主从模式下的redis服务器,如果是从服务器收到一个get的查询命令,那么从服务器会执行函数,发现 这个key已经过期了,但是从服务器并不会删除这个key,而是继续将value返回给客户端。 从服务器只有在接到主服务器发来的DEL命令之后,才会删除过期键。del命令是主服务器同步给从服务器的。

redis的持久化:

一、rdb持久化既可以手动进行,也可以根据服务器配置选项定期执行,主要是生成一个rdb文件。

BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求,而save命令会直接阻塞 主进程。在执行BGSAVE期间,客户端发送的save命令以及BGSAVE命令都会被拒绝;如果客户端发送BGREWRITEAOF命令,那么会延迟 到BGSAVE执行完成后再执行。因为这两个命令本质上都是由子进程在执行,不能同时执行只是性能方面的考虑。

定期执行BGSAVE命令(即定期生成一个rdb文件)往往都是通过配置来实现的,这个配置的含义是:服务器在多少秒以内,对数据库执行 了多少次修改操作,一旦符合这个条件,就执行一次rdb。

这里又需要提到redis的周期性执行函数serverCron,可以理解这是一个定时任务,默认每隔100ms就执行一次,前面提到了这个函数 的一个功能是定期去检查一部分key,看是否过期,过期就删除。这里它的第二个作用就是:检查save选项的配置是否满足条件,如果满足 就执行BGSAVE命令。

二、aof持久化

Sentinel系统选举领头Sentinel的方法是对Raft算法的领头选举方法的实现

redis的bitcount实现,这里相当于是计算一个二进制中1的个数,注意leetcode的计算汉明距离的题目。

variable-precision SWAR算法

一致性哈希算法

如何保证缓存和数据库数据的一致性?

redis的内存分配算法使用的是 jemalloc

stream的消息队列,借鉴了很多kafka的设计思路,但是仍然没有被大规模使用。

后续版本对列表数据结构进行了改造,使用 quicklist 代替了 ziplist 和 linkedlist。

redis面试大全 : 1、https://baijiahao.baidu.com/s?id=1594341157941741587&wfr=spider&for=pc 2、https://mp.weixin.qq.com/s/HEEhaVLNMGr4W06hPxWKjA

索引条件下推!!!