redis面试题
什么是redis?主要用来干什么?
Redis是一个开源的支持网络、可基于内存、持久化的日志型、key-value数据库
redis的数据是存于内存中的,读写速度非常快,被用于缓存,也被用来做分布式锁,还支持事务、持久化、lua脚本还有集群方案
如何保证redis和mysql的数据一致
导致数据不一致的原因
在高并发的业务场景下,数据库大多数情况下都是用户并发访问最薄弱的环节,需要redis来做一个缓冲的操作,让请求先到redis,而不是直接访问数据库,从而缓解数据库的压力
但是一旦涉及到数据更新,数据库和缓存更新的话,容易出现数据不一致的问题
- 先写数据库,再删除缓存:在删除缓存前,写数据库的线程宕机了,没有删除数据,也会出现数据不一致
- 先删除缓存,再写数据库:如果先删除缓存,还没有写数据库,另一个线程就来读取,发现缓存为空,去数据库读写数据库写入缓存,而此时缓存为脏数据
如何保证
1、延时双删策略:写库前后都进行redis.del(key)操作,并且设定合理的超时时间
public void write(Strig key,Object data){
redis.del(key);
db.updataData(data);
Thread.sleep(500);
redis.del(key);
}
- 具体步骤:
- 先删除缓存
- 再写数据库
- 休眠500毫秒,根据具体的业务情况而定
- 再次删除缓存
为什么要休眠500毫秒?
由于读写的并发性,读线程获取到时间片这一片段的执行,就会将脏数据写入缓存,线程休眠就是确保读线程结束,而写请求可以删除读请求造成的缓存脏数据
休眠写操作因此对可能出现的读操作确保结束,写操作不会对读操作进行时间片片段的争抢,从而删除操作可以删除读操作造成的缓存脏数据,最后写请求对数据库数据进行更新
删除缓存失败了,怎么办?借助mq来进行重试
异步延时删除:
- 具体步骤:
- 先删除缓存
- 再写数据库
- 触发异步写入串行化mq
- mq接收再次删除缓存
2、异步更新缓存(基于Mysql binlog的同步机制)
思路:
1、涉及到更新的数据操作,利用Mysql binlog进行增量订阅消费
2、将消息发送到消息队列
3、通过消息队列消费将增量数据更新到redis上
4、操作情况
redis的更新过程
- 全量:将所有数据一次性写入redis
- 增量:实时更新
- 增量指的是mysql的update、insert、delete操作数据
利用消息队列,推送更新redis缓存数据
1、一旦mysql产生新的写入、删除、更新等操作,可以把binlog相关信息推送到redis
2、redis再根据binlog中的记录,对redis进行操作