Redis知识整理

Redis不同数据类型底层数据结构

string

hashmap

数组实现hash,冲突通过挂链去实现

参考:https://www.jianshu.com/p/160fb0f73841

hash

ziplist+hashtable

参考:https://www.jianshu.com/p/8299aea62ab8

list

ziplist+linkedlist

参考:https://www.jianshu.com/p/c2ede9707e26

set

intset+hashset

intset 针对整数且元素数量小于512

参考:https://www.jianshu.com/p/28138a5371d0

zset

ziplist+skiplist

skiplist:跳表

参考:https://www.jianshu.com/p/fb7547369655

Redis集群

一致性hash算法:一般是0~2的32次方-1,然后每个节点2的32次方进行取模,得到当前节点在环中的某一位置,参考:https://www.jianshu.com/p/528ce5cd7e8f

在redis集群中,一共会虚拟出16384个槽位来存储数据集,这16384个槽位分别映射到各个节点上。方便集群的水平扩容

关键点:

  1. 这些槽位,需要通过命令手动来分配
  2. redis集群默认采用无中心配置,客户端与redis节点连接不需要proxy层,只需要连接集群中任一节点就行
  3. redis-cluster把所有的物理节点映射到[0-16383] slot插槽上,cluster负责维护node<->slot<->value
  4. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.

参考:https://blog.csdn.net/shubingzhuoxue/article/details/82759686

(1)为啥要设置2^14个槽位?

参考:https://zhuanlan.zhihu.com/p/99037321

理论上crc16算法可以得到2^16个数值,其数值范围在0-65535之间,取模运算key的时候,应该是crc16(key)%65535,但是却设计为crc16(key)%16384,原因是作者在设计的时候做了空间上的权衡,觉得节点最多不可能超过1000个,同时为了保证节点之间通信效率,所以采用了2^14。

(2)为什么redis集群不采用一致性哈希算法:

一致性哈希的节点分布基于圆环,无法很好的手动控制数据分布,比如有些节点的硬件差,希望少存一点数据,这种很难操作。

redis集群的槽位空间是可以用户手动自定义分配的,类似于 windows 盘分区的概念,可以手动控制大小。

其实,无论是一致性哈希还是哈希槽的方式,在增减节点的时候,都会对一部分数据产生影响,都需要我们迁移数据,当然,redis集群也提供了相关手动迁移槽数据的命令。

 

Redis主从同步方式

分为全量同步和增量同步

全量同步:第一次slave连接到master时,会发送SYNC命令申请同步,此时master会生成RDB快照文件并记录后续所有的写命令。然后master会想slave服务器发送快照文件,slave服务器得到快照文件后,丢弃所有旧数据,并载入新快照数据。然后master把同步期间所有的写命令发送给slave

增量同步:master接收到所有的写命令都会异步同步给slave

中间涉及到主从的心跳从向主同步自己的offset,然后主根据offset同步命令,同步时会有一个复制积压缓冲区

参考:https://blog.csdn.net/weixin_42711549/article/details/83061052

https://blog.csdn.net/qq_34556414/article/details/106105820

Redis的LRU算法

白话:近似LRU算法,Redis并没有用map加链表的形式存储数据的方式,而是采用在数据中存储最后一次调用时间戳加调用次数的方式,然后如果内存不够用时,就随机选择5个,然后pool中,选取其中最久次数最少的数据进行清理。如果数据量过多时,基本上接近了LRU算法
因为本身LRU算法就是一个随机接近算法
算法的变化:
redis每次获取key时都会更新数据的最后访问时间戳lru,然后构建一个16长度的池子,然后随机放入比已有lru列表小的key。满的时候,直接移除lru最小的就行了
在Redis的dict中每次按key获取一个值的时候,都会调用lookupKey函数,如果配置使用了LRU模式,该函数会更新value中的lru字段为当前秒级别的时间戳(lfu方式后文再描述)。那么,虽然记录了每个value的时间戳,但是淘汰时总不能挨个遍历dict中的所有槽,逐个比较lru大小吧。
Redis初始的实现算法很简单,随机从dict中取出五个key,淘汰一个lru字段值最小的。(随机选取的key是个可配置的参数maxmemory-samples,默认值为5).
在3.0的时候,又改进了一版算法,首先第一次随机选取的key都会放入一个pool中(pool的大小为16),pool中的key是按lru大小顺序排列的。接下来每次随机选取的keylru值必须小于pool中最小的lru才会继续放入,直到将pool放满。放满之后,每次如果有新的key需要放入,需要将pool中lru最大的一个key取出。淘汰的时候,直接从pool中选取一个lru最小的值然后将其淘汰。

参考:https://segmentfault.com/a/1190000017555834
目前Redis提供了8种的淘汰策略(默认的是noeviction):
# volatile-lru ->在设置了过期时间的键空间中,移除最近最少使用的key;
# allkeys-lru ->移除最近最少使用的key;
# volatile-lfu -> 使用具有过期集的密钥在近似LFU中进行驱逐。
# allkeys-lfu -> 使用近似的LFU退出任何密​​钥。
# volatile-random ->在设置了过期时间的键空间中,随机移除一个key;
# allkeys-random -> 随机移除一个key;
# volatile-ttl -> 在设置了过期时间的键空间中,移除将要过期的key;
# noeviction ->当内存使用达到阀值的时候,所有引起申请内存的命令会报错;

 

未完待续......

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值