Redis的数据类型
String、Hash、List、Set、ZSet、HyperLogLogs、Bitmaps、Streams
Redis的使用及相关应用场景
一、数据结构的特点
1.HyperLogLogs,基数统计统计访问次数我做过从订单出发统计某一商品的购买人数,相同的userid只能算一次,要是通过数据库做就只能保存一个json,内容是全部的userid,之后在去重放回去就慢而且长度会很长。
2.hash结构,业务上用的最频繁,相当于一个带hash索引的对象数组,购物车的设计。
3.bitmap位统计某些用户的登录每日行为,一年365个比特位,有那几天是登录的。
4.stream,基于redis的消息队列,可用作发布订阅。
二、原子性的特点
1.全局唯一自增id,在分库分表的场景可以使用基因法,去耦合关联主键,比如关联后四位。上家公司的商品的sku的id的后四位就是spu的后四位也是分类的后四位,这样未来考虑分库分表的时候,三个维度的数据可以落在一块,前面的位数就用redis的自增一批次的去获取。
2.写lua脚本,把一系列命令封装为原子性执行,去实现具体的业务场景,秒杀业务逻辑。
3.分布式锁redisson的实现。
三、时效性特点
1.记录token、验证码,做权限会话控制。
2. 限流,设定时间窗口,防至多次调用,针对下单接口,可以指定userid在2秒钟之内只能调用一次。
四、内存高效读取特点
1.缓存,针对业务场景,持久缓存(字典表)、同步缓存(订单数据)、同步续期缓存(热点商品)、异步缓存(数据量极大情况)。
2.redis search 分词,类似es的基于redis的分词。
数据持久化、过期和淘汰策略
数据持久化
一、RDB
全量的二进制数据保存为一个.rdb的文件
触发条件为 在一定的时间段内,达到写操作的阈值
数据恢复的时候快速
二、AOF
每秒钟都记录写命令至.aof文件,达到文件阈值大小的时候会进行结果的重写,把多条写命令合并,在恢复的时候由于是一条条命令重放会比rdb慢很多。
同时开启aof和rdb的话,优先使用aof策略。
持久化策略的最佳实践是使用
删除rdb那三个阈值 不开启rdb
aof-use-rdb-preamble yes
采用混合持久化,aof重写的时候采用rdb二进制的方式存储,新的命令通过记录redis命令执行,这样既能保证数据的可靠性,又能保证恢复的速度。
还有就是redis需要像数据库一样做备份,把文件scp到其他服务器。
redis的过期策略
惰性删除:get的时候,过期了再去删除。
定期删除:默认为每秒10次,抽一部分key进行过期排查,若到期的key的占80%以上,会继续进行二次删除排查,这就导致局部时间吃cpu,所以redis的key的过期时间不要全部相同,需要随机。
淘汰策略
当redis内存快满的时候,会进行key的淘汰。
allkey-lru:从所有的key中选择最近最少使用的key进行淘汰。(常用配置)
volatile-lru:设置了过期时间的key进行淘汰。(不推荐,因为内存都满了,意味着cpu繁忙,不能再去检查是否过期了)
lru一个队列栈,淘汰栈底,不断往栈顶加元素。
lfu一个队列,最少次数使用优先淘汰。
| 特性 | LFU | LRU |
|---|---|---|
| 淘汰策略 | 使用频率最低 | 最近最少使用 |
| 适合场景 | 长期热点数据 | 短期热点数据 |
| 实现复杂度 | 较高 | 较低 |
| 可能问题 | 新加入项容易被淘汰(频率低) | 突发流量可能淘汰热点数据 |
Big Key排查
一、定义
BigKey 是指存储在 Redis 中具有异常大尺寸的 key,比如
String 类型的 key,其 value 是一个json对象,读写都进行json序列化,与反序列化操作。
二、危害
操作 BigKey ,由于单线程Redis,会导致命令阻塞,慢查询,数据倾斜,持久化慢,删除慢,内存碎片的问题。
三、排查 线上紧急
先到的大key
redis-cli --bigkeys -i 0.1 # 每100毫秒采样一次
查看key的占用
redis-cli memory usage # Redis 4.0+
线下 rdb方式
Redis-RDB-Tools ,分析rdb文件,不造成线上scan 的影响。
四、解决方式
使用unlink命令异步删除,而不是delete同步方式
将大对象拆成hash结构
Redis 集群
一、主从复制
读写分离:主库负责写操作,从库负责读操作。
缺点
1.数据不一致风险,异步复制可能导致从节点数据滞后。
2.无自动故障转移,主节点故障需要手动切换。
二、哨兵模式
在主从模式的基础上,专门指派一个实例进行故障监控,当主节点宕机以后进行自动切换。
缺点
资源浪费,需要额外引入一个实例专门监控节点健康,并且主节点负责读写。
三、Redis Cluster
三主三从,redis分为16384个槽位,组成一个hash环,每个节点存放自己范围的槽位数据。满足hash一致性算法,当节点不够需要扩充时,也只需要局部的进行槽位移动就行。
优点:
高扩展性:Redis 集群模式支持多达 1000 个 Redis 节点,可以方便地通过增加节点来扩展系统的性能。
高容错性:集群模式具有自动故障转移功能,可以在节点故障后自动进行恢复。
数据分片:通过数据分片来存储数据,提高了系统的存储能力和请求吞吐量。
无中心架构:Redis 集群采用无中心架构,节点间数据共享,可动态调整数据分布。
缺点:
1.命令执行可能需要重定向一次,因为第一次命令会发送至一个节点,计算hash值,若不是这个节点需要操作的key,则需要返回客户端,具体的执行节点,重新发送一次操作命令,客户端也会缓存。
2.跨槽操作限制,比如批量操作key,mset和mget的时候,需要确保所有的key都在同一节点上操作,需要用到哈希标签,把计算hash值的部分用花括号括起来,强制将不同 Key 映射到同一槽。SET user:{1000}:name "Alice"和SET user:{1000}:age 30仅计算{1000}的哈希值,确保同槽。
四、缓存问题
一、缓存穿透
频繁查询不存在的key,导致数据频繁调用。
1.布隆过滤器(存在不一定存在,不存在一定不存在,提前缓存已经存在的key)
2.缓存空对象,即使是不存在的结果也缓存null值。
3. 提前校验请求参数的合法性,比如id必须符合业务规则。
二、缓存击穿
同一时间,访问一个热点的key,导致大量请求同时到达。
1.提前预热热点key。
2.为不同的key设置随机的过期时间,防止同时失效。
三、缓存雪崩
同一时间,大量的key过期,导致大量请求数据库。
1.为不同key设置随机的过期时间,防止同时过期。
2.多级缓存,比如本地缓存Ecache,Redis缓存。