Redis
1.为什么快?
内存数据库,无需磁盘IO;
底层数据结构,高效;
数据命令操作单线程操作,减少线程上线文切换与同步块控制的开销;
2.数据类型与对应的底层数据结构?
string -> 动态字符串
set -> 压缩列表+常量数组
zset -> 压缩列表+跳表
hash ->压缩列表+hash表
list -> 压缩列表+双向链表
3.所有的key是如何存储的?数据结构是怎样的
所有的key存储在全局hash表里;
hash表包括:key、value、next 指针,next 是用来解决hash冲突。
key、value 都指向 RedisObject。
RedisObject 结构:8字节元数据 + 8字节指针(具体的数据)
元数据:访问时间、次数、数据类型、lru等
4.压缩链表的格式?
zlbytes -> zltail -> zllen->entry->entry->zlend
entry:
5.Redis为什么使用数组与压缩链表?这两区别?
都是连续的内存,提高内存利用率;
数组存储的是相同大小的数据;
压缩链表是动态大小的数据;
使用CPU预读功能,不会降低访问速度。
6.Redis单线程是指什么?
操作key的命令是单线程,客户端的请求是放到队列,由单线程去处理命令;
7.持久化的方式?优缺点是什么
AOF append-of-file RDB;
AOF记录的是命令,AOF的文件比较大;写入时机:返回前实时写入、每秒刷盘、交给操作系统,空闲写入;
RDB是存储某一时刻的快照,大小即数据内存的大小;RDB文件是二进制数据,恢复数据比较快;
8.AOF重写 RDB期间有key更新如何实现?在内存不充裕的情况下,有什么风险?
COW,copy on write,写时复制。如果有修改命令,主线程会新开辟一块内存,将原始值放入,并执行命令操作;
fork子线程的时候,会拷贝主线程的内存页表,根据内存页表,可以找到对应的redis数据,如果比较大,会有一定的性能损失。
9.RDB 是什么时候的数据,如何实现的?
RDB存储的是某一时刻的全量数据。fork子线程去存储内存数据,采用的是写时复制。
10.主从同步如何实现?
从库执行同步命令:psync,如果原来同步过,会携带原主节点的runid,同时携带已同步的offset;psync runid offset;
主库收到命令,检查runid是否与当前runid是否一致,如果不一致,则执行全量同步;如果一致检查offset,在repl_back_buffer是否存在该offset,存在则执行增量复制,否则执行全量同步;
增量同步:利用写入缓存区,发送写命令,追上当前主库的进度;写入缓存区是环形的,如果从库offset被覆盖,需要执行全量同步
全量同步:
1.生成RDB文件,发送给从库,同时开启repl_buffer,记录增量命令;
2.从库收到RDB文件,清空原数据,初始化RDB;
3.RDB传输完成,传播同步期间的写命令,完成数据同步;
11.哨兵的工作过程?主库切换的过程
哨兵节点会定期向redis集群节点发送ping命令,如果几次没有收到节点返回pong响应,则认为节点主观下线,哨兵集群间也会同步主观下线信息,如果超过半数的哨兵都认为
某节点下线,则该节点状态改为 客观下线,哨兵广播出去,并开始做节点切换。
1.哨兵发起选举,请求成为主节点,类似raft协议,请求其它节点投票,如果其它节点纪元小于发起选举的请求纪元,则投票一次,正常来说每个纪元只投票一次;
2.哨兵收到超半数的响应后,则成为主节点,并广播;
3.哨兵开始处理节点下线,如果是从节点,直接下线即可,广播出去;如果是主节点,需要选主:
a.过滤掉网络不好的节点
b.同步复制的进度越接近越好
c.人工定优先级,越小越优先
d.比较runid,越小越优先
12.cluster模式的工作原理?主节点故障如何切换?
cluster由多个主从集群组成,每个主从集群承担一部分请求,具体哪部分请求由slot归属决定。整体划分为 16384个slot,slot->redis 会有一张路由表,集群与客户端都可以
感知。客户端请求时,根据key做CRC16 % 16384 得到对应的slot,根据slot查询到redis节点,将命令发送到对应的节点完成操作。
主从节点failover:
集群中的主节点承担哨兵的职责,会定期向集群中的节点发送ping命令,如果一段时间没有收到响应,则会认为该节点下线,并发送给其它主节点。每个主节点会记录某个节
点的下线报告,如果超过半数的主节点认为某节点下线,则下线并广播出去,客户端可以感知该信息;如果是从节点,不会发送请求到该节点,如果是主节点,该主节点对应
的从节点需要发起选举,选举也是延迟选举,复制进度越接近的越早发起选举,类似raft协议,选举通过超过半数的节点成为新的主节点,并广播出去。
13.一致性hash的原理?解决的问题?Redis为什么没用一致性hash?
普通的hash,在节点数量变化的时候,大量的key需要做迁移,一致性hash就是减少节点变化引发大量的key迁移的算法。
一致性hash,将节点组成一个环,节点也需要计算hash值,分布在环上,请求的key,hash如果落在某个节点后,则在该节点上查找对应的key。节点数量变化,只需要迁移对
应节点的hash即可。
节点hash可能会出现数据倾斜的问题,引入虚拟节点解决,虚拟节点可以分布均匀,通过虚拟节点到真实节点的映射来找到真实的节点。
redis使用的slot,代替一致性hash。
14.Bitmap的数据结构?
底层使用string存储,每个字节的bit,代表一个状态值。
15.GEO编码原理?底层的数据结构
解决地理位置的存储。将整个地图无线拆分,上下左右,分为00、01、10、11,继续拆分,011001000101010101010,每一位都可以对应到一个坐标值,底层使用zset存储
可以根据地理位置排序。
16.过期key删除的机制?
定期删除+惰性删除,定期删除 如果设置过期的key,会存放到一个过期的entry数组里面,定期从里面随机找一批,看key是否过期,过期的话就需要删除掉,每100ms执行一次;每次找到20条,可以配置;惰性删除,是访问该key的时候,如果发现key过期,则执行删除操作。
17.布隆过滤器的实现?
指定几个hash函数,对key做hash,将hash结果放入到bitmap上,分为构造阶段与判断阶段,判断的时候类似,做hash,检查bitmap上对应的位置是否一致,如果一致则认为存在,不一致则认为不存在。
18.数据淘汰策略?解释每种策略的实现
不删除。
有过期时间的key:
ttl:越快过期的key越先删除
random:随机删除
lru:最不常使用的先删除
lfu:使用频率最低的先删除
没有过期时间的:
random:随机删除
lru:最不常使用的先删除
lfu:使用频率最低的先删除
LRU实现:
传统LRU实现是采用双向链表,有访问的key移动到队列头部,淘汰的时候从尾部进行淘汰;
redis没有采用这种方式,采用的是近似LRU的实现,不是严格意义的LRU,redis key对象有8字节存储的是元数据,这里面24bit存储的是访问时间,根据访问时间判断,访问
时间靠后,说明最近没有访问,可以执行删除;
包括LRU选择的时候也是随机获取,不是严格的查找最晚访问的记录。
LFU实现:(元数据的lru字段拆分16+8,存储时间与访问频率)
lfu_decay_time = 1 衰减因子
lfu_factor_log = 10
引入时间与访问量维度的数据。元数据里面存储访问时间、请求量,会引入两个参数:衰减速度、增长因子,请求量级越大,该值增加的概率越低,最大到255。淘汰的时候也
是看访问量级,越小的可以删除。
增加概率:1/(baseVal * factor + 1),然后使用随机函数,0~1随机一个概率,比较这两个概率,如果随机的小于增加概率,则可以增加值。
19.LFU LRU 优缺点?
LFU容易历史热点数据,无法及时删除,并未访问量级较大;
LRU最近访问一次的数据,无法及时删除。
20.缓存穿透 击穿 雪崩 场景与解决方案
穿透:redis与DB都没有
击穿:redis中没有的key,穿透到DB
雪崩:大量的key过期,导致请求打到DB服务
21.分布式锁实现?
RedLock红锁,使用redis集群每个主节点都进行加锁,超过半数则代表加锁成功,释放也需要都释放
watchdog:对redis的key进行续期,防止没有操作完,key被过期;
释放锁需要使用lua脚本 get compare del 原子执行。
22.Codis集群实现方案?优缺点
引入proxy层,进行key到集群的路由,zk存储路由表信息
client -> proxy -> redis节点
缺点:稳定性风险,层级多 依赖多
优点:运维成熟
23.Redis事物 ACID如何实现的?
通过multi -> 命令入队 -> exec cancel
原子性:
开启事物后
命令入队阶段有语法错误的命令,执行阶段会报错,可以保证一致性;
命令入队阶段无错误,执行的时候报错,不会回滚,无法保证原子性;
开启事物后,可以通过watch机制,查看key是否被修改,如果被修改,事物需要取消;
24.pipeline
通过将命令打包发送到服务端;集群模式下需要进行改造,才能支持。 不保证原子性,mget 保证原子
redis 集群模式,failOver:https://blog.csdn.net/yh88623131/article/details/125573769
数据迁移:https://www.cnblogs.com/aozhejin/p/15950665.html
java syncronized
https://blog.csdn.net/chenzengnian123/article/details/122683264
https://blog.csdn.net/chenzengnian123/article/details/122685382