- redis为什么这么快?
- 纯内存操作
- 单线程操作,避免了线程上下文切换
-
NIO 多路复用机制。IO多路复用程序会将文件事件,放在一个队列里。文件事件分派器从队列中读取,转发到不同的事件处理器中。
redis的数据结构用在什么场景下?
string:value可以是字符串,也可以做计数器。
list: 可以做简单的消息队列;使用lrange可以做分页功能。
set: 去重;可以做交集、并集、差集等操作
hash:是一个map
sorted set:top N 排行榜;延时队列。key的过期策略和内存淘汰机制
定期删除 + 惰性删除
定期删除是每隔100ms,抽取一部分key检查。
这种组合方式并非完美,有些过期的key可能未能及时删除。这时候就用到了内存淘汰策略。
这里介绍LRU:
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。(推荐使用,目前项目在用这种)(最近最久使用算法)
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。(不推荐)redis和数据库的双写一致性问题
一致性问题分为强一致性和最终一致性。
缓存和数据库的联合使用,必然会存在不一致的问题。如果要求强一致性,则不能使用缓存。所以只能保证最终一致性。
解决方法从根本上来说,只能降低不一致问题发生的概率:要先更新数据库,再删除缓存。删除缓存的时候,可能会失败,这时可以提供一个补偿措施,比如利用消息队列。缓存穿透
定义:黑客故意请求缓存中不存在的数据,导致所有请求都达到数据库上。
提供一个拦截机制,比如使用布隆过滤器,内部维护一系列合法有效的key,判断key是否合法。
布隆过滤器判断一个元素是否在一个集合中,可能还有一个误识别的问题,就是某些非法的key可能被判断在这个集合里。但是数量不多,所以可以接受。
布隆过滤器的问题只有add和isExsit操作,不支持delete。如果isExsit返回true,只能说明该元素有较大可能在集合中;如果返回false,则一定不会在集合中。
- 缓存雪崩
定义:缓存同一时间大面积失效,这个时刻的请求都会被打到服务器上。
- 缓存失效的时间,可以使用在某个范围内的随机值,避免集体失效。
- 双缓存:我们有两个缓存,缓存 A 和缓存 B。缓存 A 的失效时间为 20 分钟,缓存 B 不设失效时间。自己做缓存预热操作。然后细分以下几个小点:从缓存 A 读数据库,有则直接返回;A 没有数据,直接从 B 读数据,直接返回,并且异步启动一个更新线程,更新线程同时更新缓存 A 和缓存 B。