Code前端首页关于Code前端联系我们

Redis数据库雪崩宕机原因分析及解决方案,附13条发展建议

terry 2年前 (2023-09-26) 阅读数 45 #数据库

我公司最近发生的事故以及如何避免以及如何处理优化。

间接原因有很多。技术跟不上业务的发展。这是从每天数百万到数万的一大进步。公司不重视系统优化,缺乏技术开发人员。

第一次宕机

20180913年的某个时刻,公司某服务型项目的RDS实例连接急剧增加,CPU占用率达到100%,其他应用程序的请求全部被拒绝。整个过程如下:

1。监控报警显示RDS的CPU使用率达到80%以上。 DBA 介入并准备 KILL 缓慢的 SQL

2。 1分钟内,没有发现明显阻塞的SQL,CPU持续上升到99%

3.5分钟。8分钟内,出现大量应用报警和拒绝服务攻击。 RDS监控显示大量慢SQL。请联系服务器数据库提供商寻求帮助

4。 8分钟之内,进行一次主备数据库切换(公司会受损,但也无能为力),问题没有发现)

5。 9分钟内,部分业务恢复,但部分业务订单的召回消息累计超过20万条,备库CPU占用率也持续上升

6。 15分钟内,备库CPU使用率超过97%,业务再次中断。切换回主库,限流

7。 20分钟内,关闭部分次要应用的交通入口

8。 25分钟内,主数据库CPU使用率恢复正常

9。 30分钟内,逐步打开关闭的限电应用程序

10。 35 分钟内,所有应用程序恢复正常

11。下一步是与服务器数据库提供商一起创建应急小组。优化可能的慢 SQL。虽然有些慢SQL可能已经解决了,但这次没有查出具体问题,为几天后再次发生宕机事件埋下了伏笔

事故影响

特定服务型项目的服务不可用数万分钟,导致数十万订单减少,数百万资金损失。特定服务型项目的业务增长非常迅速。高峰期数据库QPS超过35000,系统负载较大。在高峰期,如果同时执行多条全表扫描SQL,数据库压力会急剧增大,应用超时增加,前端应用超时,用户重试,流量增加,形成雪崩效应。主要原因是一些老项目的SQL查询性能较差,所使用的主数据库对数据库影响较大。数据库QPS太高,但由于人力原因一直没有实现缓存方案。应提高处理慢 SQL 问题的优先级

改进计划

1。为每个应用创建数据库账号,并严格按照规范使用

2.立即实施缓存优化计划,优先处理慢SQL问题,目前检测到的慢SQL(查询时间)超过1S)集中

3。升级数据库配置

4。将非核心业务迁移到新的RDS实例 进入

第二次宕机

由于上次宕机的原因还没有找到,所以本次宕机是可以预见的20180919,依然是同样的“菜谱”和原来的“味”。对于相同的 RDS,CPU 飙升至 100%,随后出现拒绝服务攻击和停机。第一次体验,直接主从切换,几十秒就恢复了所有业务,但还是严重影响了公司业务和形象

原因分析

恢复业务后,公司陷入紧急状态召开紧急研究会,当然以我的水平是不允许参加的。公司高层人员、高层技术架构、DBA以及各个项目的经理一起召开会议。在这次会议中,我查看了各个项目的日志以及后台监控数据,发现当RDS数据库的CPU暴涨时,Redis数据库的内存几乎是100%,然后急剧下降。第一次停机的情况是一样的。下一步是联系服务器数据库提供商并调用过去一周内的所有 Redis 命令。最后发现当时正在运行一个keys *...*命令。公司的一位工程师执行了keys模糊匹配命令来清理无用的key,但没想到模糊匹配keys *会触发Redis锁,导致Redis锁住,CPU加1,导致所有调用链。路径过期并被卡住。当Redis锁的几秒结束后,所有请求流量都会发送到RDS数据库,造成数据库雪崩,导致数据库崩溃。

改进计划

1.所有线上操作都必须由操作和维护组成,然后才能执行。运维部门正在逐步快速收回各种许可证

2。添加新的 Redis 实例并将其分离

3。如果需要使用常用命令作为按键,请使用扫描命令

总结

本次事件中的两起事故均系人为操作造成。如果技术人员看过Redis开发规范,会发现建议禁用该按键命令。此外,在线指挥作业在作业前必须经过运维评估。我猜工程师是老员工,有权限,然后直接跑。另外,公司业务发展很快,技术却跟不上。 ,这是非常非常危险的,并且大大增加了停机的可能性。当业务量不大的时候,工程师的操作是没有问题的。同时,同时性也不是很大。但现在随着公司的成长和发展,业务量成倍增长,但技术扩张却没有增长那么快。公司技术人才匮乏也是一方面。大多数人在维护旧项目的同时致力于新功能,但对于项目的重要任务、结构优化,却人手少得多,而且项目优化的优先级不高。这也是一个很大的原因。类似的情况很有可能发生,新的服务化建设迫在眉睫

终于可以在线操作了,无论你多么小心的指挥,你都可能无法承受因为你的一个符号而引发的事故

Redis开发建议

最后是一些Redis的开发规范和建议

1。冷热数据分离,不要把所有数据都放在Redis中

虽然Redis支持持久化,但所有Redis数据存储都在内存中,成本昂贵。据公司介绍[QPS大于5000]建议仅将高频热点数据存储在Redis中。对于低频冷数据,可以采用MySQL/ElasticSearch/MongoDB等基于磁盘的存储方式,不仅节省内存成本,还能减少数据量,加快运算速度。更快更高效!

2。不同的业务数据应该分开保存

不要将所有不相关的业务数据放在一个Redis实例中。建议新公司申请新的独立机构。由于Redis是单线程的,独立存储会减少各种业务操作的影响,提高请求响应速度;也避免了单实例内存数据量的过度膨胀,出现异常时可以更快的恢复服务!在实际使用中,redis最大的瓶颈一般是CPU。由于它是单线程作业,因此很容易填满逻辑CPU。您可以使用redis代理或分布式解决方案来提高redis的CPU使用率。

3。必须为存储的key设置超时时间

如果应用程序将Redis作为缓存,则必须为存储的key设置超时时间!因为如果不设置的话,这些key就会一直占用内存而不被释放,造成巨大的浪费。而且,随着时间的推移,内存使用量会越来越大,直到达到服务器的内存限制!另外,关键超时时长要根据业务综合评估,并不是越长越好!

4。对于要存储的大文本数据,必须对其进行压缩和存储

当您将大文本[+超过500字节]写入Redis时,必须对其进行压缩和存储!在Redis中存储大文本数据不仅占用大量内存,而且在流量大时很容易填满网卡,导致整个服务器上的所有服务不可用并引发雪崩效应,导致所有系统瘫痪。 !

5。线上Redis禁止使用Key的正则匹配操作

Redis是单线程进程。当在线KEY大量时,运行效率极低[时间复杂度为O(N)]。该命令执行时,会严重阻塞线上其他命令的正常请求,直接导致Redis服务在高QPS情况下崩溃!如果您有类似需求,请改用scan命令!

6。可靠的消息队列服务

Redis List 通常用于消息队列服务。假设消费者程序从队列中取出消息后立即崩溃。但由于消息已被检索且未正常处理,则可能会认为该消息丢失,从而可能导致业务数据丢失或业务状态不一致。发生。为了避免这种情况,Redis提供了RPOPLPUSH命令。消费者程序会原子地从主消息队列中取出消息并将其插入到备份队列中,直到消费者程序完成正常的处理逻辑。从备份队列中删除。同时,还可以提供守护进程。当发现备份队列中的消息过期时,可以将其放回到主消息队列中,以便其他消费者程序可以继续处理。

7。小心Hash、Set等全功能集合结构

使用HASH结构存储对象属性时,一开始只有有限的十几个字段。 HGETALL经常用来获取所有成员,这也很有效,但随着时间的推移,业务发展会将字段扩展到数百甚至数百个。目前使用HGETALL会带来效率急剧下降、网络地图频繁填满等问题[时间复杂度O(N)]。此时,建议按照公司拆分为多个Hash结构;或者如果大部分操作需要获取所有属性,则可以将所有属性序列化为STRING类型的存储!使用 SMEMBERS 操作 SET 结构类型时也是如此!

8。根据业务场景合理使用不同的数据结构类型

目前Redis支持多种类型的数据库结构:String、Hash、List、Set、Sorted Set、Bitmap、HyperLogLog和地理空间索引(geospatial)等,需要您选择根据业务场景选择合适的类型。常见的包括:String可以作为常规K-V、count类;哈希可以用作商品、经纪商等包含多种属性信息的对象; List可以用作消息队列、粉丝/关注列表等;可以使用集合进行推荐;排序集可用于放置等!

9。命名约定

虽然Redis支持多种数据库(默认32个,可以配置更多),但除了默认库#0外,其他库都需要额外请求才能使用。因此,使用前缀作为命名空间可能更明智。另外,当使用前缀作为命名空间来分隔不同的键时,最好在程序中使用全局配置。应严格避免直接在代码中编写前缀的做法,因为这会导致可维护性较差。例如: 系统名称: 公司名称: 业务数据: 其他 不过要注意,按键名称不要太长,尽量清晰易懂,自己衡量一下

10。线上禁止使用monitor命令

生产环境禁止使用monitor命令,高并发情况下monitor命令会有内存爆炸的隐患,影响Redis性能

11。禁止大字符串

如果 1mb 密钥每次重复写入 10 次,核心集群将禁用 1mb 字符串大密钥(尽管 redis 支持 512MB 字符串大小)第二,会导致网络IO写入达到10MB;

12。 redis容量

单实例内存大小不建议太大,建议在10~20GB以内。建议一个redis实例包含的key数量控制在1kw以内。如果单箱密钥数量过多,过期密钥可能无法及时重用。

13 可靠性

需要定期监控redis的健康状况:使用各种redis健康监控工具。如果做不到,可以定期返回redis info信息。尝试使用连接池进行客户端连接(长链接和自动重连)

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门