redis
2020-12-23 18:06:28 0 举报
AI智能生成
对线面试之Redis!
作者其他创作
大纲/内容
单线程模型原理
redis 的 文件事件处理器 是单线程的。
文件事件处理器包含4个组件:
多个socket;IO多路复用程序; 文件事件分派器;事件处理器;
文件事件处理器包含4个组件:
多个socket;IO多路复用程序; 文件事件分派器;事件处理器;
文件事件处理器 处理 客户端socket请求过程:
1,客户端发送请求,通过socket与redis服务器端建立连接
2,redis server socket会生成 AE_READABLE 事件 ,redis 的 IO 多路复用程序 会轮询监听所有的socket 然后将 事件 放到队列中去
3,redis 文件事件分派器 会把队列中的socket 分派给对应的 事件处理器关联)
4,事件处理器包括:
连接应答处理器(将AE_READABLE 事件 与命令请求处理器)
命令连接处理器(将从连接应答处理器过来的 socket 中的key_value 读取出来,并在内存中做设置,然后连接命令回复处理器)
命令回复处理器(给客户端回复响应,返回给redis 服务端的 AE_WRITABLE 事件对应响应)
1,客户端发送请求,通过socket与redis服务器端建立连接
2,redis server socket会生成 AE_READABLE 事件 ,redis 的 IO 多路复用程序 会轮询监听所有的socket 然后将 事件 放到队列中去
3,redis 文件事件分派器 会把队列中的socket 分派给对应的 事件处理器关联)
4,事件处理器包括:
连接应答处理器(将AE_READABLE 事件 与命令请求处理器)
命令连接处理器(将从连接应答处理器过来的 socket 中的key_value 读取出来,并在内存中做设置,然后连接命令回复处理器)
命令回复处理器(给客户端回复响应,返回给redis 服务端的 AE_WRITABLE 事件对应响应)
为什么redis是单线程的效率还高的原因?
1,基于纯内存操作。
2,实现核心是基于非阻塞的IO多路复用程序机制:只做轮询监听,不做处理,没有阻塞。
3,因为是单线程的,所以避免了多线程的频繁上下文切换的问题。
2,实现核心是基于非阻塞的IO多路复用程序机制:只做轮询监听,不做处理,没有阻塞。
3,因为是单线程的,所以避免了多线程的频繁上下文切换的问题。
支持的数据类型
基本数据类型
string
正常存key _ value
hash
一般用来存简单的对象
list
存放可重复的,有顺序的数据,比如微博用户评论列表等
set
存放唯一的,无序的数据,比如取微博多个用户共同的好友等
sorted set
存放有序且唯一的数据
高级数据类型
Bitmaps
String类型上的一组面向bit操作的集合,不是真正的数据结构。使用场景是记录用户是否进行过搜索
Hyperloglogs
用于计算唯一事物的概率数据结构,使用场景是统计用户在搜索框中搜索的次数
GEO
可以将用户给定的地理位置(经度和纬度)信息储存起来
过期策略
定时删除
给redis key设置过期时间,每隔多少毫秒之后,redis会随机从过期了的key中删除数据
缺点:因为是随机,所以可能有些过期了的key并没有被删除,依旧占用内存
惰性删除
当查询redis key时,redis会去检查下,此key是否过期,过期的话就删除,不返回缓存中的value
缺点:只有查询的时候才做删除,所以可能会有大量过期key占用内存
一般线上生产会将两种过期策略组合使用
内存淘汰机制
当redis设置的内存大小满了的时候,会触发设置的redis的内存淘汰机制
一般使用allkeys_lru 策略,就是根据lru算法,删除不常使用的缓存数据
lru算法
通过双向链表实现。先进先出,新增,修改,查询时会把对应key的数据放到头节点,并更改其他节点对应顺序,如果内存满了,会删除last节点数据
集群高并发高可用
一主多备,水平扩容,读写分离
master主要负责写数据,slave从机主要负责读数据,slave机器可以水平增加多台,从master复制数据即可
主从数据复制,保证数据一致性:完全重同步,部分重同步
完全:一般用于新机器同步数据,master生成rdb文件,并将后续的增量数据存到缓冲区,slave读取rdb同步完后再执行缓冲区的写数据,则保证数据一致。
部分:一般用于slave宕机,导致的主从数据不一致。实现是通过复制偏移量offset,master和slave都有一个offset,正常情况下一致,当slave宕机重启后,重连master,会比较offset,如果不一致,则同步当前offset后的AOF文件记录的写数据。有一个需要注意的是,slave存放的有一个runid记录master机器ip,如果重连后runid不一致,则表示不是同一台master,slave需要删除数据重新同步。
完全:一般用于新机器同步数据,master生成rdb文件,并将后续的增量数据存到缓冲区,slave读取rdb同步完后再执行缓冲区的写数据,则保证数据一致。
部分:一般用于slave宕机,导致的主从数据不一致。实现是通过复制偏移量offset,master和slave都有一个offset,正常情况下一致,当slave宕机重启后,重连master,会比较offset,如果不一致,则同步当前offset后的AOF文件记录的写数据。有一个需要注意的是,slave存放的有一个runid记录master机器ip,如果重连后runid不一致,则表示不是同一台master,slave需要删除数据重新同步。
高可用之“哨兵”机制(sentinel)
主要是通过心跳来监听master机器状态,如果master机器宕机则重新选举slave为master,原来master重连后作为slave机器。“哨兵”一般也会设置集群。
“脑裂”问题:当master因为网络问题短暂连接不上,“哨兵”认为此master“宕机”重新选举了新的master,但是原master还在接收写请求,这样就会导致数据丢失问题。
解决:设置两个参数:
min-slaves-to-write 2 设置连接到master上的slave最少连接数为2。
min-slaves-max-lag 10 设置slave连接master进行数据同步的延迟时间不能超过10秒,如果超过则master不接受任何写请求。
解决:设置两个参数:
min-slaves-to-write 2 设置连接到master上的slave最少连接数为2。
min-slaves-max-lag 10 设置slave连接master进行数据同步的延迟时间不能超过10秒,如果超过则master不接受任何写请求。
高可用常见问题
redis缓存雪崩:大量redis同时过期,导致直接访问数据库
解决:
发生前 给每个rediskey过期时间设置随机数。
发生时 给数据库访问设置限流,可以通过MQ实现,保证数据库不被打挂。
发生后 重启redis,通过rdb和AOF恢复数据。
发生前 给每个rediskey过期时间设置随机数。
发生时 给数据库访问设置限流,可以通过MQ实现,保证数据库不被打挂。
发生后 重启redis,通过rdb和AOF恢复数据。
redis缓存穿透:大量请求查询一个redis不存在的值,导致直接访问数据库
解决:
临时将这个不存在的值写入到redis中。
布隆过滤器。
临时将这个不存在的值写入到redis中。
布隆过滤器。
redis缓存与数据库不一致问题
先删缓存,再更新数据库(高并发下会出现脏数据)
解决:
1,延时双删策略(删缓存;更新数据库;等待1秒再删缓存)
2,给缓存设置过期时间
1,延时双删策略(删缓存;更新数据库;等待1秒再删缓存)
2,给缓存设置过期时间
先更新数据库,再删缓存(推荐,高并发下出现脏数据的情况很小,缺点是原子性不友好)
删除缓存失败时出现的不一致性
解决:
利用canal订阅mysql的binlog文件,对更新的数据key放到mq中,通过消费自己来重试删除缓存操作
利用canal订阅mysql的binlog文件,对更新的数据key放到mq中,通过消费自己来重试删除缓存操作
数据一致性(持久化)
RDB快照
BGSAVE自动生成,会生成一个子进程,不影响主进程
也可手动生成SAVE,但是会阻塞进程,不推荐
AOF文件日志
保存redis写操作的日志,增量读取并恢复数据
比较
RDB文件小,恢复数据速度快,但是在写入文件时宕机可能会丢失数据
AOF文件大,恢复慢,但是恢复数据较全面,不易丢失数据
redis其他作用
数据库
redis自带redisDB,底层数据库为hash表
缓存
消息中间件
list实现
ipush增加消息到头部,rpop获取尾部消息
发布订阅模式
stream类型
手动通过ack确定消息是否被消费
一般不推荐使用redis用于消息队列,因为对待消息处理存在很多问题,而rabbitmq,kafka,rocketmq等优秀的消息队列可以可以更好的处理消息消费问题
0 条评论
下一页