基本数据类型
- String字符串:可以是字符串、整数或浮点数。使用场景:保持JSON字符串
- List列表:双向字符串链表,数据可重复。可对链表的两端进行push和pop操作。使用场景:队列、栈,或者缓存微信消息流数据
- Set集合:字符串的无序、不可重复集合。使用场景:一天里面所有限单的仓,key 日期,value 所有限单的仓编码
- Hash散列:包含键值对的无序散列表。使用场景:一天里面一个仓冷藏/冷冻/常温限单值,key 日期_仓编码,field 温层,value 对应温层的限单值
- Zset有序集合:使用场景:一天单量TOP10的仓,key 日期,value 仓编码,score
缓存穿透:
缓存和数据库都没有数据
1.如果是非法请求,对参数进行校验,过滤非法值。
2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。
3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。(误杀,可能hash冲突,存在不一定真的存在)
缓存击穿:
指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。
1.使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先获取Redis锁,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
2.“永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
3.缓存预热,系统启动的时候,先把查询结果预存到缓存中,以便用户后面查询时可以直接从缓存中读取,以节约用户的等待时间
缓存雪崩:
缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
1.设置过期时间随机,即让过期时间相对离散一点
2.构造Redis高可用集群
Redis 内存淘汰策略
volatile-lru:当内存不足时,从设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰;
allkeys-lru:当内存不足时,从所有key中使用LRU(最近最少使用)算法进行淘汰。
volatile-lfu:4.0版本新增,当内存不足时,在过期的key中,使用LFU算法进行删除key。
allkeys-lfu:4.0版本新增,当内存不足时,从所有key中使用LFU算法进行淘汰;
volatile-random:当内存不足时,从设置了过期时间的key中,随机淘汰数据;
allkeys-random:当内存不足时,从所有key中随机淘汰数据。
volatile-ttl:当内存不足时,在设置了过期时间的key中,根据过期时间进行淘汰,越早过期的优先被淘汰;
noeviction:默认策略,当内存不足时,新写入操作会报错。
总结
随机
TTL 过期时间里找到更早时间的key
LRU 最近最少使用
LFU 淘汰低频数据
Redis 的持久化机制
RDB
把某一个时刻的内存快照数据,以二进制的方式写到磁盘上
手动触发:
- save命令,使Redis处于阻塞状态,直到RDB持久化完,才会响应其他客户端发来的命令
- bgsave命令,fork出一个子进程进行持久化操作,主进程只在fork过程中有短暂的阻塞,子进程创建之后,主进程就可以响应客户端的请求了
自动触发:
- save m n: 在m秒内,如果有n个键发生变化,则会自动触发持久化,通过bgsave执行
- 主从同步:全量同步时,会自动触发bgsave命令,生成rdb发送给从节点
优点:性能高,数据恢复快,只有一个dump.rdb文件,方便持久化
缺点:会丢数据;fork子进程过程中,如果数据集比较大,可能会导致整个服务器停止服务几百毫秒,甚至1秒钟
AOF
以日志的形式,记录服务器所处理的每一个写、删除操作,放到缓冲区,再根据设置的同步策略,写到磁盘。当AOF文件变大,会定期对AOF名称重写,对命令进行合并,达到压缩的目的。
实时把数据追加到AOF文件里
优点:不会丢数据
缺点:数据恢复慢
AOF文件比RDB更新频率高,优先使用AOF还原数据
AOF比RDB更安全也更大
RDB性能比AOF好
如果俩个都配置了,优先加载AOF
分布式锁
七种方案!探讨Redis分布式锁的正确使用姿势 - 哔哩哔哩
- set ex(过期时间 秒) px(过期时间 毫秒) nx(不存在则set成功) + 校验唯一随机值,再删除(防止锁被其他线程释放)
- 利用lua脚本来保证多个redis操作的原子性
- 同时还要考虑锁过期,需要额外的一个看门狗定时任务来监听锁是否需要续约。它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。
- 同时还要考虑redis节点挂掉后的情况,需要采用红锁的方式来同时向N/2+1个节点申请锁,都申请到了,才能获取锁成功,这样就算其中某个节点挂了,锁也不能被其他客户端获取到
Redisson
解决分布式锁可能存在锁过期释放,业务没执行完的问题
原理:线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。
Redis和Mysql数据一致性
- 延时双删,先删除Redis缓存数据,再更新Mysql,延迟几百毫秒,再删除Redis缓存数据
Redis的过期策略
定时过期
特点:为每个key创建一个定时器,到期立即清理
优点:及时释放内存
缺点:占用大量CUP资源
惰性过期
特点:只有当访问一个key时,才会判断该key是否已过期,过期则清理
优点:节省CPU
缺点:内存不能及时释放,会存在大量过期key没有被再次访问,无法被清理
定期过期
特点:每隔一段时间,会扫描一定数量的key,清理其中已过期的key。
优点:是定时过期和惰性过期的的折中方案,使得CPU和内存资源达到最优的平衡效果
MySQL与Redis 如何保证双写一致性
缓存延时双删 (删缓存,删DB,sleep,再删一次缓存)
删除缓存重试机制
读取binlog异步删除缓存
Redis线程模型
Redis基于Reactor模式开发了文件事件处理器,是单线程的。采用IO多路复用机制,同时监听多个Socket, 根据Socket上的事件类型,选择对应的事件处理器来处理这个事件。
单线程快的原因
- 纯内存操作
- 基于非阻塞的IO多路复用机制
- 避免了多线程上下文切换带来的性能问题
为什么Redis 6.0 之后改多线程呢?
因为redis的性能瓶颈在于网络IO而非CPU,使用多线程能提升IO读写的效率,从而整体提高redis的性能。
Redis 事务机制
- 开始事务(MULTI)
- 命令入队
- 执行事务(EXEC)、撤销事务(DISCARD )
Redis不支持事务回滚机制
Redis的Hash 冲突怎么办
链式哈希,rehash
Redis 和 Tair的区别
Tair 存储引擎分3种:
RDB:就是Redis
MDB:内存型,高性能
LDB:高一致性,持久化,交易链路使用
Tair支持动态扩容,Redis不支持
Tair 的MDB、LDB的value只支持字符串
Redis集群策略
主从模式:
特点:一个Master,多个Slave,读写分离
缺点:Master挂了,后续的写请求全部失败
哨兵模式:
哨兵模式原理_Redis的哨兵模式是如何实现的呢?_戴少鹤的博客-CSDN博客
Redis(开发与运维):43---Sentinel之(哨兵的安装与部署、哨兵配置参数、部署技巧、哨兵API)_董哥的黑板报的博客-CSDN博客
特点:监听Master状态,Master挂了,会从Slave节点选取Master节点
缺点:在线扩容问题没解决
集群模式:
特点:多主多从,每个主节点数据不同,通过Slot槽实现数据分片
优点:高可用,支持动态扩容
缺点:维护成本高
主从同步
- 从节点执行slave of 主节点IP 主节点端口
- 从节点的定时任务发现主节点信息,建立和主节点的socket连接
- 主节点把数据复制给从节点
全量模式:
- 从节点发送psync命令给主节点
- 主节点通过bgsave命令fork子进程,生成数据快照RDB文件,同步Slave节点
- 子节点清空老数据,载入新的RDB文件。此过程是阻塞的,无法响应客户端命令
增量模式:
从节点发送psync runid offset命令,runid表示从节点id, offset表示从节点当前偏移量
Master收到数据后,同步修改到Slave节点。如果主节点offset和从节点offset差异过大,超过缓冲区长度,只能执行全量复制