一为什么要使用redis?
主要是性能和并发两个方面,性能:redis响应迅速,可以将执行耗时特别久,且结果不频繁变动的sql,将运行结果放入缓存,后面的请求就会去缓存中读取。并发:在大并发的情况下,所有请求直接访问数据库,数据库就会连接异常,这个时候,久需要Redis做一个缓冲操作,而不是直接访问数据库。
二优缺点?
主要以下四个方面的问题:
1缓存和数据库双写一致性的问题
2缓存雪崩问题
3缓存击穿问题
4缓存并发竞争问题
三单线程redis为什么这么快?
1纯内存操作
2单线程操作,避免了频繁上下文切换
3采用了非阻塞I/O多路复用机制
四Redis过期策略及内存淘汰机制
采用定期删除和惰性删除策略
redis每隔100毫秒检查是否有过期的key,有过期的就删除,这里是随机抽取key进行检查,所以导致很多key到时间没有删除。惰性删除派上用处,就是在你获取某个key时,redis会检查一下这个key如果设置了过期时间,那么是否过期了,过期了就删除。
如果你又没有请求这个key,这时需要内存淘汰机制:当内存不足以容纳新写入数据时,在键 空间中,移除最近最少使用的key。
五缓存穿透和缓存雪崩问题
缓存穿透:黑客故意请求缓存中不存在的数据,导致所有请求直接打到数据库上,导致数据库异常。
解决方案
利用互斥锁,缓存失效时,先去获得锁,得到锁之后,再去请求数据库,没得到锁,休眠一段时间重试。
缓存雪崩:缓存同一时间大面积失效,这个时候又来了一波请求,结果都打到数据库上,导致数据库异常。
解决方案:给缓存失效时间加一个随机值,避免集体失效;
六:并发竞争key的问题
同时有多个子系统去set一个key。
对这个key操作不要求顺序,准备一个分布式锁,大家抢锁,抢到就set操作
要求先set valueA,再set valueB,再set valueC的顺序。在设置值时,保存一个时间戳:
系统A key1 {valueA 3:00}
系统B key1 {valueA 3:05}
假设这时b先抢到锁,将key1设置为 {valueA 3:05},然后a抢到锁,发现自己时间戳早于缓存中时间戳,就不进行set操作了。
利用队列,将set方法变成串行访问也可以