在上篇文章【项目经验】Redis Sentinel从工程中下线并对业务迁移-进行中-CSDN博客有说到迁移的计划。最近一直按照计划进行迁移,期间遇到了不少问题。总结如下:
一、key未设置过期时间
redis基于内存存储,主要作用是缓存。当大量的key未设置过期时间时,redis内存空间的利用率会降低,执行效率也会受影响。
弊端:
1. 内存占用
最直接的弊端是可能会造成内存使用持续增长。如果没有过期机制自动删除不再需要的数据,随着时间推移,Redis实例可能会消耗越来越多的内存。这最终可能导致内存溢出,影响Redis服务的稳定性和性能。
2. 资源管理困难
不设置过期时间使得手动管理Redis中的数据变得复杂。需要额外的机制或策略来监控和控制数据量,避免不必要的数据累积。
3. 性能下降
随着数据量的增加,查找、读取或写入操作的效率可能会降低,因为更多的内存消耗意味着更频繁的磁盘交换(如果开启了虚拟内存)。此外,大量的无期限数据可能导致缓存命中率下降,从而降低了Redis作为高性能缓存的优势。
4. 影响其他业务
如果Redis用作多个应用或服务的共享缓存,未过期的key可能会挤占其他应用需要缓存的空间,影响整体系统的资源分配和效率。
5. 风险增加
在极端情况下,如服务器硬件故障或重启前,未过期的key会全部写入磁盘(如果配置了持久化),延长了恢复过程,增加了数据丢失的风险。
6. 淘汰策略受限
Redis提供了多种内存淘汰策略(如LRU、LFU等),用于在内存不足时决定哪些数据应该被移除。但当大多数或所有key都没有过期时间时,这些策略的效果会大打折扣,可能无法有效地释放内存给更重要的数据使用。
如何解决?
根据业务的特点设置合理的过期时间,并检查从redis中获取不到时,从表中或接口获取源数据的方案是否仍然可行。
因为之前没有过期时间,业务中的数据大概率一直从redis中获得的,如果表或接口的源数据发生了变更,业务可能并无感知。此时key过期,查询源数据,可能导致业务无法正常执行。
二、big key
目前排查结束未发现big key,但有一些value缓存的是对象信息,而且未设置过期时间,同时业务中只使用了其中某几个属性值。后续我将把这些属性信息查出来单独缓存和超时时间,并停止对缓存对象的使用。
虽然没发现big key,我们也再聊一下big key的识别、弊端和解决方案。
如何找到big key?
1. 使用MEMORY USAGE命令
直接在Redis命令行界面使用MEMORY USAGE key_name命令,可以查看指定Key的内存占用情况。通过遍历并比较各个Key的内存使用量,可以找出占用内存较多的大Key。
2. Redis自带的--bigkeys 选项
虽然实际中--bigkeys并不是一个直接可用的Redis命令,可以使用类似功能的脚本或客户端工具来扫描数据库并统计不同类型中最大的Key。对于字符串类型,此方法能直接反映出value的字节大小;对于集合、列表、有序集合、哈希等复杂类型,则主要统计元素数量,可能需要进一步的分析来确定实际占用的内存大小。
3. 使用Redis客户端工具
利用如redis-cli、Redigo等客户端工具,编写脚本来遍历所有Key,并计算它们的大小进行排序。这样可以系统地识别出占用内存最多的大Key。
4. 手动或自动化脚本扫描
编写脚本使用SCAN命令安全地遍历Redis中的Key空间,结合MEMORY USAGE或其他方法计算每个Key的大小,然后根据大小阈值标记出大Key。这种方法可以灵活定制扫描和评估逻辑。
5. 分析RDB文件
在Redis执行备份生成的RDB文件中,也可以分析Key的大小。虽然这通常不作为实时监控的手段,但在离线分析或计划性维护时,通过解析RDB文件可以获取详细的Key信息。
6. 使用第三方工具
工具如RdbTools、RedisInsight等提供了图形界面和高级分析功能,可以帮助更容易地识别大Key,同时提供数据可视化和优化建议。
选择合适的方法时,应考虑操作的便利性、准确性以及对Redis服务运行时的影响。在生产环境中,特别注意避免因扫描操作引起的服务压力。
弊端:
1. 内存使用不均衡
在Redis Cluster集群环境下,大Key可能导致数据分区不均,因为数据是基于Key的哈希值分布的。这会引起某些节点内存使用过高,而其他节点则相对空闲,破坏了集群的负载均衡能力。
2. 阻塞问题
由于Redis采用单线程模型处理客户端请求,操作大Key(如HGETALL、SMEMBERS等命令)可能非常耗时。这不仅会导致该操作期间其他快速操作被阻塞,还可能引起客户端超时,严重影响系统的响应时间和吞吐量。
3. 故障切换风险
长时间的阻塞操作可能触发如Sentinel(Redis的高可用组件)的故障转移机制,即便实际上Redis服务器并未发生故障,这会进一步影响服务的稳定性。
4. 备份和恢复效率
大Key的存在会增加Redis数据备份(如RDB快照)的时间和存储空间需求,同时在数据恢复时也会消耗更多时间,延长了故障恢复窗口。
5. 性能瓶颈
频繁访问大Key会占用大量网络带宽,尤其是在网络条件不佳的情况下,可能导致网络拥塞,进一步影响Redis的性能。
6. 管理难度
大Key使得内存管理更加复杂,可能导致内存碎片化严重,影响内存的有效利用,同时也给内存优化和问题排查带来挑战。
7. 潜在的数据丢失风险
在一些极端情况下,如Redis实例突然崩溃且没有配置持久化,大Key中的数据可能来不及保存到磁盘,从而导致数据丢失。
如何解决?
1. 拆分Key
将大的数据结构拆分成多个小的Key。例如,一个包含大量元素的Hash或Set可以拆分为多个小的Hash或Set。
对于列表类型的Key,如果元素过多,可以考虑按时间或元素数量进行切分,存储到多个列表中。
2. 使用分片
在设计阶段,考虑使用客户端分片或Redis Cluster自动分片功能,将数据分散到多个Redis实例上,避免单个Key过大影响整个实例。
3. 优化数据模型
重新审视和优化数据模型,减少冗余数据,使用更高效的数据结构。
对于频繁查询但不经常更新的数据,考虑使用缓存穿透技术,直接从客户端或另一层缓存中读取,减轻Redis负担。
4. 设置过期时间
为大Key设置合理的过期时间,确保不再需要的数据能够自动被清理。
5. 使用Redis Modules
对于特定场景,如时间序列数据,可以考虑使用Redis Modules,如RedisTimeSeries,它为特定类型的数据提供了更高效的存储和查询方式。
6. 监控与自动化
实施定期监控和自动化脚本,及时发现并处理大Key,比如使用Redis自带的监控工具或第三方监控系统,结合脚本自动拆分大Key。
7. 限制操作
对于操作大Key的命令(如HGETALL, SMEMBERS等),限制其在低峰时段使用或直接禁止使用,转而使用更细粒度的命令(如HSCAN, SSCAN)分批处理数据。
8. 数据压缩
在不影响业务逻辑的前提下,对存储的数据进行适当的压缩,减少内存占用。
9. 调整Redis配置
根据实际情况调整Redis的配置参数,如增加内存限制、优化持久化策略等,以更好地适应大Key带来的挑战。
三、找不到读取方或找不到写入方
背景:
我们的工程是从一个大的module工程中独立出来的,当时可能迁的着急,导致迁出了很多冗余的代码。这次redis迁移过程,整理出了没有写入或者读取方的key,经过排查,和当时工程迁移有关。
如何解决?
这些key需要发出来挨个和各组对,看其他组是否还在使用。如果多组共用在一个业务中,看看如何拆分;如果大家都不使用了,就得下掉了。
也给我们后面编程提了醒,在代码设计时,要避免这种问题产生,秉持高内聚,低耦合的原则,并且“如无必要,不增实体”。
总结:
以上是Redis Sentinel从工程中下线并对业务迁移过程中遇到的一些问题和总结到的业内常用的方法,希望能为读者朋友带来帮助。