数据结构
一.底层数据结构
简单动态字符串
字符串是redis自己构建的一种名为简单动态字符串(SDS)的抽象类型
结构包括:
len:SDS所保存字符串的长度
free:buf数组中未使用字节的数量
buf[ ]:字节数组,用于保存字符串
特点:
获取字符串长度的时间复杂度为O(1)
杜绝缓存溢出
减少修改字符串带来的内存重分配次数
应用场景:
存储字符串,整型数据
Key-value键值对的键是字符串对象
SDS还被用做缓冲区:AOF缓冲区等
扩容:
空间预分配
注:
如果对SDS进行修改之后,SDS的长度(即len属的值)将小于1MB,那么程序分配和len属性同样大小的未使用空间,这时SDS len属性的值和free属性的值相同。SDS的长度(即len属的值)将大于等于1MB,那么程序分配1MB未使用空间
惰性空间释放
2.链表
提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。
结构:
head(表头节点)
tail(表尾节点)
len(链表所包含的节点数量)
dup(节点复制函数)
free(节点值释放函数)
match(节点对比函数)
应用场景:
链表是列表键的底层实现之一。
特性:
1.双端:链表节点带有prev 和next指针,获取某个节点的前置节点和后置节点的复杂度都是O(1)。
2.无环:表头节点的prev 指针和表尾节点的next指针都指向null,对链表的访问以NULL为终点。
3.带表头指针和表尾指针:通过list结构的head指针和tail指针,程序获取链表的表头节点和表尾节点的复杂度为O(1)。
4.带链表长度计数器:程序使用list结构的len属性来对list持有的链表节点进行计数,程序获取链表节点数量的复杂度为O(1)。
5.多态:void*指针保存节点值,通过dup,free,match为节点设置类型特定函数,用于保存各种类型值
3.字典
保存键值对的数据结构
应用:redis数据库,哈希
结构:
type(类型特定函数)
private(私有数据)
ht(哈希表)
rehash(rehash索引,当未进行rehash是为-1)
扩缩容:
渐进式hash
演示
4.跳跃表
结构:
header(表头节点)
tail(表尾节点)
level(层数)
length(长度)
应用场景:
有序集合键
5.整数集合
整数集合是集合的底层实现之一
结构:
encoding(编码方式)
length(元素数量)
content(元素数组)
场景:
集合键
注:不支持降级
6.压缩列表
结构:
zlbytes(内存字节数)
zltail(表尾节点距起始地址字节数)
zllen(节点数量)
entryX(节点)
zlend(特殊值0xFF,用于标记压缩列表末端)
节点结构:
Previous_entry_length(前一节点的长度)
encoding(数据类型及长度)
content(值)
应用场景:
列表,hash
二.数据结构
1.String
字符串对象编码可以是整数和简单动态字符串
2.列表
list编码可以是链表和压缩列表
压缩列表的场景(下面条件同时满足):
列表对象保存的所有字符串长度都小于64字节
列表对象保存的元素数量小于512个
3.Hash
hash编码可以是字典和压缩列表
压缩列表的场景(下面条件同时满足):
哈希对象保存的所有键值对的键和值字符串长度都小于64字节
哈希对象保存的键值对数量小于512个
4.集合(Set)
集合编码可以是整数集合和字典
整数集合的场景(下面条件同时满足):
集合对象保存的所有元素都是整数
集合对象保存元素个数不超过512个
5.有序集合
集合编码可以是压缩列表,跳跃表
压缩列表的场景(下面条件同时满足):
列表对象保存的所有字符串长度都小于64字节
列表对象保存的元素数量小于128个
持久化
RDB持久化
AOF持久化
全量备份,一次保存整个数据库
增量备份,一次保存一个修改数据库的命令
保存的间隔较长
保存的间隔默认为一秒钟
数据还原速度快
数据还原速度一般,冗余命令越多,还原速度越慢
执行SAVE命令时会阻塞服务器,但手动或者自动触发BGSAVE都不会阻塞服务器
无论是平时还是进行AOF重写时,都不会阻塞服务器
更适合数据备份
更适合用来保存数据,通常意义上的数据持久化,在appendfsync always模式下运行时,redis的持久化方式和一般的mysql数据库的持久化方式是一样的
集群模式
哨兵(sentinel)
Master故障处理;
确认master下线
1.Sentinel以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他Sentinel在内)发送PING命令.当没有收到主服务器有效回复时,该Sentinel认为该主服务器主观下线
2.该Sentinel向监控该主服务器的其他Sentinel发送is-master-down-by-addr命令。其他Sentinel收到命令后检查该主服务器是否下线,并回复。当Sentinel收到确认下线的回复超过半数时,则该主服务器客观下线。
2.选举 sentinel leader
某sentinel认定master客观下线后,该sentinel会先看自己有没有投过票,如果投过,则一定时间内自己不会成为leader,如果没有投过,则有可能成为leader。
该sentinel将当前配置纪元(epoch)加一,向其他节点发送is-master-down-by-addr命令,其中runid是该sentinel的运行ID。
其他sentinel接收到命令后,可以同意或者拒绝,采用先到先得。
该sentinel不断统计自己的票数,当票数超过sentinel数量一般后,则该sentinel为leader。
如果在给定时间内没有选出leader,则再一段时间后继续选举,直到选出leader为止
3.从slave中选举master
过滤掉主观下线的节点
从服务优先级
从服务的复制偏移量
运行ID最小的