01-Redis服务器启动流程
2021-11-26 17:42:25 0 举报
Redis知识图谱
作者其他创作
大纲/内容
数据结构
fork()
zipset
dictEntry 2* key* val* next
记录压缩列表表尾节点距离压缩列表的起始地址有多少字节,通过这个偏移量可以O(1)确定表尾节点的地址
6
主从不一致
syslog
Hash{A: \"foo\
List
......
String\"I'm a Plain Text String!\"
B6
snapshot(binary)
穿透
GEO
数据分片
数据丢失
configparsing
zltail
抖动
原始链表
阻塞
缓存
backtrace
Hyperloglog
ziplist
List{A -> B -> A -> D -> E}
Hyperloglog00110101 11001110
list
Streams->{id1=tim1.seq1(A:\"xyz\
Timing缓存服务平台的10库就那么香吗?
Bitfield{23334}{11234567}{9876}
jemalloc
单链表
networking
quicklist
* key
性能
9
5
* val
4
简单动态字符串SDS
DNS
特殊值,用于标记压缩列表的末端
主从库
1
整个压缩列表占用的内存字节数
timers
* redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象,最大能存储 512MB。 * 使用场景:缓存/计数器/分布式锁/Web集群session共享/分布式系统全局序号(不用每次都拿,一次拿1000个放到内存中)... * 实战:实现分布式的id生成器,可以使用incr的思路,但是实际中会比这复杂多
* O(1)的时间复杂度* 诸多使用场景,总结来看都是以唯一的标识作为key,value任意都行,一般是value较少改动
淘汰机制
Set
内存
cluster clients
event loop
HLLhyperloglog
set
embeded
ZSet
B3
dict map
触发rehash -> 新的哈希表ht[2] size=ht[1] * 21KW key一次copy完?渐进式rehashtypedef struct dict { dictType *type; void *privdata; dictht ht[2]; int rehashidx; // 目前正在运行的安全迭代器的数量 int iterators;} dict;Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;
OS
列表节点和节点的长度,有了长度就能通过偏移量快速找到下一个节点的内存地址
entryN
redis replicas
skiplist
cluster replicas
* HLL是一种算法,并非完整的数据结构* 极小空间完成独立数据量统计 - 是计数啊* 适用于数据量巨大的统计,数据量小了,优势不大* 一般bitmap与hll配合使用,bitmap用于标识,hll用于计数,如github统计和展示提交的commit看板* 实战:统计页面UV,统计网站访问IP数,统计在线用户数,统计搜索词条数
8
cluster masters
B1
Bitmaps00110101011001110001
RDB
AOF
green threads
Hash
cluster protocol
主从复制
dictEntry 1* key* val* next
AOF重写
全局哈希表dict *dict
Bitmap
3
string
高性能主线
String
有序链表只能逐一查找,导致查找很慢,于是就出现了跳表。跳表在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位。
entry1
diskless
异步机制
2
encoding
config
7
哨兵机制
线程模型
集群应用
sentinel
双向链表O(N)
负载均衡
datastructure
Streams
* 存储地理位置信息,并提供计算距离等操作* 数据类型是zset,是一种位置编码算法,基于Z阶曲线,进行空间分割;特点,每个位置都有一个geohash编码,Geohash保证,如果编码得到的字符串的共同前缀长度越长,两点之间的距离就越近,但是反过来是不保证的,两个很接近的点,可以有不同的/很少的共同字符串前缀* 查看附近好友
content
数据热点
journal(text)日志
dictEntry
* BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。* 统计每个用户一年的登录天数* 用户在线状态 Timing业务中 3000W用户大于需要4M
缓存应用
B2
应用维度
压缩列表结构
hash
跳表O(logN)
Redis
intset
哈希表结构:typeof struct dictht { dictEntry **table; // 哈希表数组 unsigned long size; // 哈希表大小 unsigned long sizemask; // 哈希表大小掩码,用于计算索引值 unsigned long used; // 该哈希表已有节点的数量} dictht;typeof struct dictEntry { void *key; // 键 union { void *val; uint64_tu64; int64_ts64; } v; // 值 struct dictEntry *next; // next属性是指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键值对连接在一起,以此来解决键冲突(collision)的问题} dictEntry;typeof struct dict { dictType *type; // 类型特定函数 void *privdata; // 私有数据 dictht ht[2]; // 哈希表 int rehashidx; // rehash索引}当要将一个新的键值对添加到字典里面时,程序需要先根据键值对的键计算出哈希值和索引值,然后再根据索引值,将包含新键值对的哈希表节点放到哈希表数组的指定索引上面。* 解决哈希冲突:当有两个或以上数量的键被分配到了哈希表数组的同一个索引上面时,我们称这些键发生了冲突,Redis的哈希表使用链表法来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以用这个单向链表连接起来,这就解决了键冲突问题。因为链表节点没有指向链表表尾的指针,所以为了考虑速度,程序总是将新节点添加到链表的表头位置。* rehash:随着操作的不断执行,哈希表保存的键值对会逐渐增多或减少,为了让哈希表的负载因子(load factor)维持在一个合理的范围之内,当哈希表保存的键值对数量太多或太少时,程序需要对哈希表的大小进行相应的扩展或者收缩。扩展和收缩哈希表的操作可以通过rehash(重新散列)操作来完成,步骤如下:1. 为字典ht[1]哈希表分配空间。如果执行扩展操作,ht[1]的大小等于第一个大于等于ht[0].used*2的2的n次方幂;如果执行收缩操作,ht[1]的大小大于等于ht[0].used的2的n次方幂2. 将保存在ht[0]重大额所有键值对rehash到ht[1]上面:rehash指的是重新计算键的哈希值和索引值,然后将键值对放置到ht[1]哈希表的指定位置上。3. 当ht[0]包含的所有键值对都迁移到了ht[1]之后(ht[0]变为空表),释放h[0],将ht[0]设置为ht[1],并在ht[1]新创建一个新的哈希表,为下一次rehash做准备。* 渐进式rehash如果ht[0]中保存的键值对非常大,那么一次性将这些键值对全部rehash到ht[1]的话,庞大的计算量可能会导致一段时间内停止服务。为了避免rehash对服务器性能的影响,redis采用分多次,渐进式地将ht[0]中的键值对慢慢rehash到ht[1]中。redis中的hash维护了一个索引计数器变量rehashidx,在rehash期间每次对字典执行添加,删除,查找或者更新操作的时候,程序除了执行指定的操作外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完之后,程序将rehashidx属性的值增一。* 渐进式rehash执行操作期间的哈希表操作因为在进行渐进式rehash的过程中,字典会同时使用ht[0]和ht[1]两个哈希表。例如要在字典中查找一个键的话,程序会先在ht[0]中进行查找,如哦没有找到就会继续在ht[1]找。添加一个键值对只会在ht[1],ht[0]不会执行任何添加操作。这样ht[0]包含的键值对数量只减不增
fsync()
psync
占用飙升
replication
sentinel protocol
redis masters
bitmap
网络层
streaming
L1
* Redis 5.0新增数据结构,主要用于消息队列,解决以前Redis消息持久化和主从复制功能,提供访问偏移量* 数据量小可用,大的话还是走MQ三件套
存储层
污染
dict set
雪崩
处理层
rand()
整数数组 insetO(N)
当初没设置过期时间,现在没用了,也不敢删除的那些key,你想咋办?
zlbytes
整数数组是集合键的底层实现之一,当一个集合中只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。typedef struct intset { uint32_t encoding; // 编码方式 uint32_t length; // 集合包含的元素数量 int8_t contents[]; // 保存元素的数组。数组中的值按照大小从小到大有序地排列,并且数组中不包含任何重复项}* 升级:添加一个新元素到整数集合,新元素类型比现有的元素类型都要长,整数集合先进行升级,然后将新元素添加到整数集合中。 * 根据新元素类型,扩展整数集合底层数组的空间大小,并为新元素分配空间 * 将所有元素的类型转换成新元素的类型,并把转换后的元素放到正确的位置,同时保证有序性。为什么转换类型,为了保持所有类型都是一样,这样的话cpu寻址快 * 将新元素放到正确的位置整数集合一旦升级就不能降级,编码就会一直保持升级后的状态
sorted set
thread
哈希桶HashBucket
cluster
高可扩展主线
dictEntry 3* key* val* next
previous_entry_length
coroutines
内存层
typedef struct dictEntry { void *key union { void *val; uint64_t u64; int64_t s64; } v; struct dictEntry *next;} dictEntry;
数据分布
sentinel clients
async I/O
Redis问题画像
N
zlend
epoll网络模型
sds
Zset
persist/restore
哈希表 hashtableO(1)
signals
zipmap
linked
Redis系列知识分享0. 开篇词1. Redis整体结构图2. 数据结构篇3. 线程模型和网络模型4. AOF和BOD5. 主从模式应用浅讲6. 集群应用模式浅讲7. 千万级热键处理方案8. Redis三座大山
切片集群
数据结构应用
BigKey
系统维度
高可用主线
entry2
压缩列表 ziplistO(N)
B4
B5
Timing服务平台面对无效的BigKey是怎么删除的?
sync
Key
两个维度,三条主线
zllen
记录压缩列表包含的节点数量,当这个属性的值小于65535取真实值,大于的话需要遍历整个列表才能知道
0 条评论
下一页