1. redis存在的问题(常见):
缓存与数据库双写一致性
缓存穿透
缓存击穿
缓存雪崩
并发竞争问题
2. redis是一个单线程的工作模型,获取数据效率高。
纯内存操作
单线程操作,避免上下文切换
非阻塞I/O多路复用模式(只有单个线程,通过跟踪每个I/O流的状态,来管理多个I/O流。)
3. redis存储的数据类型及对应用法:
String:一般用于做一些复杂的计数等功能
hash:存放结构化的对象,便于操作其中的某个字段,如单点登录、session控制等。
list:类似消息队列的使用时。利用lrange命令,做基于redis的分页功能,性能极佳,用户体
验好。取行情信息。就也是个生产者和消费者的场景。
set:全局去重。
sorted set:类似排行榜。
4. redis过期策略及淘汰机制:
定期删除+惰性删除机制。
定期删除:redis每隔100ms随机抽样检查是否有过期的KEY。单纯使用此方式可能会导致部分key过期后无法删除。
惰性删除:每次使用到一个KEY时,都检查一下是否过期。如过期则删除。两种删除方式均使用的情况下,仍然会存在一部分KEY过期了且一直未使用,还是无法删除。
配置内存淘汰策略:# maxmemory-policy volatile-lru
noeviction:内存不足时,写入报错。(一般不使用)
allkeys-lru:内存不足时,写入新KEY,移除掉不常使用的。(使用较多)
allkeys-random:内存不足时,写入新KEY,随机删除已有的KEY。(一般不用)
volatile-lru:内存不足时,写入新KEY,删除设置过期时间的KEY空间中最不常使用的。(把redis既当缓存,又做持久化存储的时候才用)
volatile-random:内存不足时,写入新KEY,随机删除设置过期时间的KEY空间中的KEY。
volatile-ttl:内存不足时,写入新KEY,删除设置过期时间的KEY空间中设置了更早过期时间的KEY。
ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
5. redis与数据库的双写一致性:
先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。
6.1 redis缓存穿透:
黑客故意去请求缓存中不存在的KEY,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方式:
利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试
采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。
6.2 redis缓存击穿:
黑客故意去请求缓存中的热点key,当KEY失效时,大量请求直接击穿了缓存,到了数据库上。
解决方案:
可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key访问数据,或可以在凌晨服务器访问量较小的时候进行数据更新进数据库,同时使用linux定时任务写一个脚本来模拟访问热门数据将数据加载回redis。
7. redis缓存雪崩:
缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:
给缓存的失效时间,加上一个随机值,避免集体失效
使用互斥锁,但是该方案吞吐量明显下降了。
双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点:
从缓存A读数据库,有则直接返回。
A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
更新线程同时更新缓存A和缓存B。
8. redis并发,竞争KEY:
多个子系统去set一个key。
解决方式:
如果对这个key操作,不要求顺序:准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可
如果对这个key操作,要求顺序:存储数据时存入一个时间戳,后面抢到线程的进程处理时,先根据时间戳判断。
9. redis持久化方式:
快照(rdb-redis database):将存储在内存的数据以快照的方式写入二进制文件中。
每隔一段时间,对内存中的数据进行一次快照,保存到rdb文件中,主从同步可以实现异步。但是,如果间隔时间过短会影响到redis的性能,如果间隔时间过长,在间隔时间段内关闭或重启redis可能导致部分数据丢失。
仅附件文件(AOF-append only file):使用AOF持久时,服务会将每个收到的写命令通过写函数追加到文件中(appendonly.aof)。
随着时间增长,aof文件会越来越大,可能会让进程如同假死一样。
10. redis的主从复制:
主节点:负责写数据,定期同步数据到从节点。
从节点:负责读数据。