基本数据类型
- String:键值对形式,最简单的数据类型
应用场景:计数(String有自增/递减令明令-incr/decr key),简单缓存 - List:双向链表,按照插入顺序排序,可从左/右插入/弹出数据
应用场景:消息队列等 - Map:value值为map类型,可以处理更加复杂的数据结构
应用场景:一些对象的存储等 - Set:无序集合,自动排重,有交集,并集,差集等操作
应用场景:适合于对多个集合数据的处理 - ZSet:与set类似,相比set多了一个用来排序的属性score
应用场景:排行榜,带有权重的数据集合等
使用注意
- key的命名最好有一定规则,便于管理
- redis是单线程,串行执行命令。在线上环境禁止使用keys等命令导致阻塞
- 生命周期的设置,对热点数据的缓存生命周期应当避免过于集中,防止同一时间大量热点数据失效,请求全部直接进入数据库
线上问题及解决方案
- 数据一致性
问题:如何保证数据库数据与缓存数据的一致性
解决方案:1 查询时先取缓存,缓存为空取数据库并补充到缓存 2 更新操作先清空缓存,再更新数据库并补充到缓存 3 高并发场景下引入队列,将写操作和读操作放入队列依次执行,等待写操作完成再读
- 缓存雪崩
问题:缓存压力过大导致redis服务崩溃,请求全部进入数据库
解决方案:1 使用redis高可用方案,主从+哨兵,redis cluster等防止服务崩溃 2 后备方案,如果服务仍然意外崩溃,及时限流&降级,防止连锁问题 3 对redis服务崩溃后的数据恢复问题,使用redis持久化
- 缓存穿透
问题:请求的key不在缓存中,绕过了缓存查数据库
解决方案:1 查不到的数据也增加一个缓存(无法解决恶意攻击的问题) 2 使用布隆算法,识别key
- 缓存击穿
问题:热点数据key失效瞬间,大量请求直达数据库
解决方案:1 针对缓存生命周期可设置永不失效或者使用定时任务维护达到不失效的效果 2 使用互斥锁,防止大量请求同时进入,待一个请求查询完成后重构缓存,后面的请求即可走缓存查询
- 并发竞争
问题:并发场景下,对同一个key的写操作
解决方案:1 分布式锁确保同一时间只有一个实例操作 2 使用时间戳判断数据有效性
redis持久化
- RDB(默认方案)
实现方式:创建一个子进程,与父进程共享数据段,将数据写入一个临时文件,写入成功后会替换掉之前的文件
触发方式:在指定的时间间隔内执行了指定的操作次数
优点:只有一个数据文件,便于管理维护;性能较好;适用于大数据量的恢复
缺点:由于是在指定时间间隔内执行,存在丢失部分数据的情况 - AOF
实现方式:将写命令以日志的形式存储在文件中,若文件过大,会触发文件重写操作,减小文件体积
优点:不存在数据丢失情况
缺点:相比RDB性能较差,文件大,恢复速度慢