缓存的部署方式
- 单机
- 主从
- 哨兵
- 集群
特性 | 主从(Master-Slave) | 哨兵(Sentinel) | 集群(Cluster) |
---|---|---|---|
数据分片 | 不支持 | 不支持 | 支持,基于 slot 进行水平分片 |
高可用性 | 部分支持(手动故障转移) | 高可用性,自动故障转移 | 高可用性,自动故障转移及数据分片 |
配置复杂度 | 低 | 中 | 高 |
扩展性 | 低至中 | 中 | 高 |
适用场景 | 中小规模应用,读多写少 | 需要高可用性且不需要分片的应用 | 大规模分布式应用,需水平扩展和高可用性 |
一致性 | 弱(异步复制,可能有延迟) | 弱(同主从) | 强(单 slot 内一致) |
数据备份 | 支持,通过从节点实现 | 支持,通过 Sentinel 管理的从节点 | 支持,通过集群内的从节点和分片 |
CAP
-
分区容忍性(P):
在Redis集群模式中,数据自动分片到不同节点。即使部分节点由于网络故障而无法访问,其余节点仍可继续提供服务。
-
可用性(A):
使用哨兵模式(Sentinel)进行故障转移。当主节点宕机时,哨兵能自动将一个从节点提升为新的主节点,确保服务的持续可用性。
-
一致性(C):
在Redis的事务特性中,可以使用WATCH命令实现乐观锁,这提供了一种条件式的一致性。此外,通过等待多个从节点应答,可以提高数据一致性的保证。
cp还是ap
连接池
- jedis
- Lettuce
- Redisson
类型 | 优点 | 缺点 |
---|---|---|
jedis | 简单易用,API直观。 支持完整的Redis命令集。 性能较高,因为它是同步的,并且直接与Redis服务进行交互 | 不支持Redis集群的自动重定向。 在4.0版本之前,不支持Redis哨兵。 连接池管理相对简单,可能不如Lettuce灵活。 4.0版本开始支持Redis集群和哨兵,但社区认为它在这方面的支持不如Lettuce成熟。 |
Lettuce | 基于Netty的事件驱动架构,性能优越,尤其在高并发环境下。 支持Redis集群的自动重定向。 支持Redis哨兵和主从复制。 提供了高级功能,如异步操作、发布订阅、超时处理等。 连接池管理功能强大,支持多种配置。 | API相对复杂,学习曲线较陡。 由于是异步的,对于习惯同步编程的开发者来说可能不太直观。 |
Redisson | 提供了丰富的分布式数据结构,如分布式集合、队列、锁等。 基于Jedis,但封装了更多的高级功能,简化了分布式环境下的操作。 支持Redis集群和哨兵。 提供了分布式锁的实现,这对于分布式系统中的同步问题非常有用。 支持自动重连和故障转移。 | 由于提供了更多的封装和功能,性能可能略低于Jedis和Lettuce。 学习曲线相对较陡,因为需要理解额外的分布式数据结构和概念。 社区和生态系统相对较小,可能不如Jedis和Lettuce成熟。 |
多级缓存
过期和淘汰策略
- 惰性删除(Lazy Expiration):
键的过期检查只在以下两个时刻进行:- 当你访问这个键时,如果键已经过期,那么它会被删除。
- 当你向数据库添加一个新的键时,如果内存超出了 maxmemory 指令指定的最大限制,那么 Redis 会从数据库中删除一些键以释放内存。
- 这种方法的优点是节省 CPU 资源,因为不需要定期检查键是否过期。
- 缺点是可能会有过期键在内存中停留较长时间,直到它们被访问或者触发内存淘汰机制。
- 定期删除(Active Expiration):
- Redis 每隔一段时间(默认是 100 毫秒)就会随机抽取一些设置了过期时间的键进行检查,如果发现它们已经过期,就会将它们删除。
- 这种方法可以保证过期键尽快被删除,减少内存占用。
- 缺点是会消耗更多的 CPU 资源,因为需要定期执行检查。
更新策略
更新策略 | 存在问题 |
---|---|
先更新数据库,再更新缓存 | 1、更新缓存的时候失败了(或者更新的时候晚了被其他线程读取到的还是旧值),导致缓存中存的一直都是脏数据; 2、多个线程在更新时,因为两个更新步骤执行顺序不一致,可能会导致数据错乱 |
先更新缓存,再更新数据库 | 1、不太推荐,业务上一般把mysql最后保障 2、多线程环境下,A、B两个线程有快有慢,最后可能导致缓存与数据库不一致; |
先删除缓存,再更新数据库 | 1、多线程下,A还没更新完数据库;B进来查缓存没查到,就会读取数据库的旧值写入缓存(延迟双删:可以等一会再删除一遍缓存) 2、删了缓存假如这个时候流量激增查询这个key,会导致缓存击穿数据库 |
先更新数据库,再删除缓存(推荐) | 假如删除失败或者来不及,就会被其他线程读取到旧值(存在一定时间数据不一致但是会保证最终一致性) |
使用场景
锁
优化
集群有偏移问题
大key问题
热点Key问题
慢查询问题
内存碎片问题
缓存雪崩;
缓存击穿;
缓存穿透
数据预热