- 基于内存;
- 单线程减少上下文切换,同时保证原子性;
- IO多路复用;
- 高级数据结构(如 SDS、Hash以及跳表等)
缓存雪崩:
redis缓存的key在同一时间大量失效,导致大量请求全部打到数据库,造成数据库挂掉
解决方法:
- 随机设置key的失效时间
- 热点数据key永不过期
- 跑定时任务,在缓存失效前刷新新的缓存
缓存穿透
对redis和数据库中没有的数据进行不断查询,造成数据库挂掉
解决方法
- 对参数进行校验
- 将不存在的数据缓存在redis缓存中,设置k-v都为null,并设置一个很短的过期时间
- 布隆过滤器
缓存击穿
具体的热点key一直在高并发,key突然失效,数据库压力过大宕机
解决方法
- 设置热点key永不过期
- 加互斥锁,第一个查询到的数据放入缓存,走缓存,每过一端时间更新缓存
缓存预热
将热点数据提前缓存到redis中,防止数据库压力过大宕机
解决方法
- 手动写热点缓存
先更新数据库,再删除缓存
因为缓存的写入速度远远大于数据库的写入速度,保证缓存为空,再去查找一遍数据库,即可保证每次查找的数据和缓存都相同
Redis 通过主从加集群架构,实现读写分离,主节点负责写,并将数据同步给其他从节点,从节点负责读,从而实现高并发。
答案很简单,因为 Redis 是单线程的,所以 Redis 提供的 API 也是原子操作。但我们业务中常常有先 get 后 set 的业务常见,在并发下会导致数据不一致的情况。
如何解决
- 使用 incr、decr、setnx 等原子操作;
- 客户端加锁;
- 使用 Lua 脚本实现 CAS 操作。
- String(字符串):缓存、限流、分布式锁、计数器、分布式 Session 等。
- Hash(字典):用户信息、用户主页访问量、组合查询等。
- List(列表):简单队列、关注列表时间轴。
- Set(集合):赞、踩、标签等。
- ZSet(有序集合):排行榜、好友关系链表。