1、redis 五种对对象类型和底层数据结构
类型常量 | 对象的名称 |
---|---|
REDIS_STRING |
字符串对象 |
REDIS_LIST |
列表对象 |
REDIS_HASH |
哈希对象 |
REDIS_SET |
集合对象 |
REDIS_ZSET |
有序集合对象 |
对应的底层数据结构有8种:
编码常量 | 编码所对应的底层数据结构 |
---|---|
REDIS_ENCODING_INT |
long 类型的整数 |
REDIS_ENCODING_EMBSTR |
embstr 编码的简单动态字符串 |
REDIS_ENCODING_RAW |
简单动态字符串 |
REDIS_ENCODING_HT |
字典 |
REDIS_ENCODING_LINKEDLIST |
双端链表 |
REDIS_ENCODING_ZIPLIST |
压缩列表 |
REDIS_ENCODING_INTSET |
整数集合 |
REDIS_ENCODING_SKIPLIST |
跳跃表和字典 |
I. 字符串对象可以编码成long, raw和embStr。如果字符串可以转换成long,就用long存储;如果字符串的长度小于39,就用embStr,其比raw的优势:1)embstr的创建只需分配一次内存,而raw为两次,同样释放内存也是如此;2)embstr的objet和sds放在一起,更好地利用缓存带来的优势。
II. list对象有ziplist和linkedlist,ziplist是内存中的一块连续区域,只需要分配一次,但为了保证内存的连续性和插入复杂度O(N),所以每次插入都会重分配一次内存。linkedlist是一种双向链表,节点中存放pre和next两个节点。
III. hash对象,底层是ziplist和hashtable.ziplist是key1,value1,key2,value2这样的顺序存放来存储的,当对象数目不太多的时候,这种存储结构效率比较高。dict是一个字典,其中有长度为2的数组,一个用来存放真正的数据,一个用来rehash时中转数据。
IV. set集合对象,集合对象的编码可以是intset或者hashtable,intset是一个有序的整数集合,查找效率是O(logN),但插入可能由O(logN)升级到O(N)。
V. zset有序集合,编码可能两种,一种是ziplist,另一种是skiplist与dict的结合。ziplist中存放的是score和members,跳跃表实现里有序集合的快速查找,大多数情况下与平衡术相当。每一列都代表一个节点,保存了member和score。
2、redis内存的数据持久化RDB和AOF
3、redis数据的淘汰策略。redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。redis 提供 6种数据淘汰策略:
voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
LRU 数据淘汰机制是这样的:在数据集中随机挑选几个键值对,取出其中 lru 最大的键值对淘汰
4、redis的过期策略
常见的过期策略有三种:
1)定时删除,在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除
- 优点:保证内存被尽快释放
- 缺点:若过期key很多,删除这些key会占用很多的CPU时间;定时器的创建耗时,性能影响严重。
- 优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的。
- 缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
- 优点:通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用--处理"定时删除"的缺点,并且定期删除过期key--处理"惰性删除"的缺点
- 缺点:在内存友好方面,不如"定时删除",在CPU时间友好方面,不如"惰性删除"
redis采用的是惰性删除+定期删除策略。过期的key对RDB和AOF没有任何影响,在RDB和AOF之前,会对key先进行过期检查,恢复的时候,仍会对key进行过期检查,过期的key不会写入数据库。
5、redis cluster
I. Redis Cluster特点如下:
- 所有的节点相互连接;
- 集群消息通信通过集群总线通信,集群总线端口大小为客户端服务端口+10000,这个10000是固定值;
- 节点与节点之间通过二进制协议进行通信;
- 客户端和集群节点之间通信通过文本协议进行;
- 集群节点不会代理查询;
II. redis cluster分区的实现:Redis Cluster中有一个16384长度的槽的概念,每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务。master维护了16384/8字节的位列结构,通过位列结构判断slot是否被管理。Redis Cluster并不会代理查询。
III. redis重新分片:重新分片意为槽到集群节点的映射关系要改变,键到槽的映射关系不变,因此当重新分片的时候,如果槽中有键,那么键也是要被移动到新的节点。槽迁移的过程中有一个不稳定状态,这个不稳定状态会有一些规则。
预备迁移槽的时候槽的状态首先会变为MIGRATING状态,当客户端请求到达时,会有:
1)key存在就处理返回;
2)key不存在,返回ASK,并不会刷新客户端中node的映射关系;
3)key包含多个命令,如果都存在返回处理结果,如果部分存在,返回客户端TRYAGAIN,直到所有key迁徙完成。