文章目录

  • 第一次宕机
    • 事故影响
    • 原因分析
    • 改进方案
  • 第二次宕机
    • 原因分析
    • 改进方案
  • 总结
  • Redis开发建议
    • 1.冷热数据分离,不要将所有数据全部都放到Redis中
    • 2.不同的业务数据要分开存储
    • 3.存储的Key一定要设置超时时间
    • 4.对于必须要存储的大文本数据一定要压缩后存储
    • 5.线上Redis禁止使用Keys正则匹配操作
    • 6.可靠的消息队列服务
    • 7.谨慎全量操作Hash、Set等集合结构
    • 8.根据业务场景合理使用不同的数据结构类型
    • 9.命名规范
    • 10.线上禁止使用monitor命令
    • 11.禁止大string
    • 12.redis容量
    • 13 可靠性

最近的互联网线上事故发生比较频繁,20180919顺丰发生了一起线上删库事件,在这里就不介绍了。

在这里讲述一下最近发生在我公司的事故,以及如何避免,并且如何处理优化。 该宕机的直接原因是使用Redis的keys *命令引起的,一共造成了某个服务化项目的两次宕机
间接原因还有很多,技术跟不上业务的发展,由每日百万量到千万级是一个大的跨进,公司对于系统优化的处理优先级不高,技术开发人手的短缺

第一次宕机

20180913某个点,公司某服务化项目的RDS实例连接飙升,CPU升到100%,拒绝了其他应用的所有请求服务
整个过程如下:

  1. 监控报警,显示RDS的CPU使用率达到80%以上,DBA介入,准备KILL慢SQL
  2. 1分钟内,没有发现明显阻塞的SQL,CPU持续上升到99%
  3. 5分钟内,大量应用报警,并且拒绝服务,RDS的监控显示出现大量慢SQL,联系服务器数据库提供商进行协助
  4. 8分钟内,进行数据库主备切换(业务会受损,但是也没办法,没有定位到问题)
  5. 9分钟内,部分业务恢复,但是一些业务订单的回调消息堆积超过20w,备库的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模糊的匹配命令是为了清理没用的键,但是没有考虑到keys *进行模糊匹配引发Redis锁,造成Redis锁住,CPU飙升,引起了所有调用链路的超时并且卡住,等Redis锁的那几秒结束,所有的请求流量全部请求到RDS数据库中,使数据库产生了雪崩,使数据库宕机。

改进方案

  1. 所有线上操作,全部要经过运维通过后方可执行,运维部门逐步快速收回各项权限
  2. 新增Redis实例,进行分离
  3. 如果有使用类似keys正则命令需求,使用scan命令代替

总结

该事件中出现的两次事故,完全是由于人为操作引起的,如果那位工程师,看过Redis的开发规范,会发现是建议禁用keys命令的。另外,有线上的命令操作,一定要经过运维评估后方可进行操作,估计那个工程师是老员工吧,有权限,然后直接就进行操作了
另外,公司的业务发展确实很快,技术跟不上,这是非常非常危险的,极大的增加了宕机的概率
在业务量不大的情况下,那位工程师的操作是完全没什么问题的,毕竟并发也不大,但是现在,随着公司的发展,业务量的成倍成倍增加,技术的扩展却没有随着增长那么快
公司的技术人手不足也是一方面,绝大多数人都是边维护老项目边做新功能,但是对于项目的重构优化,人手却少了很多,项目优化的优先级不高,这也是很大的一个原因,极有可能出现类似的情况,新服务化构建迫在眉睫

最后的最后,线上操作的任何一条命令,再小心也不为过
因为由于你的一个符号而引起的事故可能是你所承担不起的

Redis开发建议

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

1.冷热数据分离,不要将所有数据全部都放到Redis中

虽然Redis支持持久化,但是Redis的数据存储全部都是在内存中的,成本昂贵。建议根据业务只将高频热数据存储到Redis中【QPS大于5000】,对于低频冷数据可以使用MySQL/ElasticSearch/MongoDB等基于磁盘的存储方式,不仅节省内存成本,而且数据量小在操作时速度更快、效率更高!

2.不同的业务数据要分开存储

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

3.存储的Key一定要设置超时时间

如果应用将Redis定位为缓存Cache使用,对于存放的Key一定要设置超时时间!因为若不设置,这些Key会一直占用内存不释放,造成极大的浪费,而且随着时间的推移会导致内存占用越来越大,直到达到服务器内存上限!另外Key的超时长短要根据业务综合评估,而不是越长越好!

4.对于必须要存储的大文本数据一定要压缩后存储

对于大文本【+超过500字节】写入到Redis时,一定要压缩后存储!大文本数据存入Redis,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪!

5.线上Redis禁止使用Keys正则匹配操作

Redis是单线程处理,在线上KEY数量较多时,操作效率极低【时间复杂度为O(N)】,该命令一旦执行会严重阻塞线上其它命令的正常请求,而且在高QPS情况下会直接造成Redis服务崩溃!如果有类似需求,请使用scan命令代替!

6.可靠的消息队列服务

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

7.谨慎全量操作Hash、Set等集合结构

在使用HASH结构存储对象属性时,开始只有有限的十几个field,往往使用HGETALL获取所有成员,效率也很高,但是随着业务发展,会将field扩张到上百个甚至几百个,此时还使用HGETALL会出现效率急剧下降、网卡频繁打满等问题【时间复杂度O(N)】,此时建议根据业务拆分为多个Hash结构;或者如果大部分都是获取所有属性的操作,可以将所有属性序列化为一个STRING类型存储!同样在使用SMEMBERS操作SET结构类型时也是相同的情况!

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

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

9.命名规范

虽然说Redis支持多个数据库(默认32个,可以配置更多),但是除了默认的0号库以外,其它的都需要通过一个额外请求才能使用。所以用前缀作为命名空间可能会更明智一点。
另外,在使用前缀作为命名空间区隔不同key的时候,最好在程序中使用全局配置来实现,直接在代码里写前缀的做法要严格避免,这样可维护性实在太差了。
如:系统名:业务名:业务数据:其他
但是注意,key的名称不要过长,尽量清晰明了,容易理解,需要自己衡量

10.线上禁止使用monitor命令

禁止生产环境使用monitor命令,monitor命令在高并发条件下,会存在内存暴增和影响Redis性能的隐患

11.禁止大string

核心集群禁用1mb的string大key(虽然redis支持512MB大小的string),如果1mb的key每秒重复写入10次,就会导致写入网络IO达10MB;

12.redis容量

单实例的内存大小不建议过大,建议在10~20GB以内。
redis实例包含的键个数建议控制在1kw内,单实例键个数过大,可能导致过期键的回收不及时。

13 可靠性

需要定时监控redis的健康情况:使用各种redis健康监控工具,实在不行可以定时返回redis 的 info信息。
客户端连接尽量使用连接池(长链接和自动重连)

欢迎关注公众号,细数项目中的坑,经验干货之谈

Redis的KEYS命令引起RDS数据库雪崩,RDS发生两次宕机,造成几百万的资金损失相关推荐

  1. Redis的KEYS命令引起宕机事件

    摘要: 使用 Redis 的开发者必看,吸取教训啊! 原文:Redis 的 KEYS 命令引起 RDS 数据库雪崩,RDS 发生两次宕机,造成几百万的资金损失 作者:陈浩翔 Fundebug经授权转载 ...

  2. 老大说:谁再用redis 的 keys命令,立刻给我走人

    先看现象 redis-cli keys * | args redis-cli del (error) ERR network error (30.00s) #执行了一条 keys xxxxx* 命令, ...

  3. Redis的keys命令到底有多慢?

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://blog.csdn.net/weixin_37968613/article/details/119065777 ...

  4. 关于redis的keys命令的性能问题

    KEYS pattern 查找所有符合给定模式 pattern 的 key . KEYS * 匹配数据库中所有 key . KEYS h?llo 匹配 hello , hallo 和 hxllo 等. ...

  5. 面试官:Redis 数据库内存数据满了,会宕机吗?有内存回收?

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~ 中文详细注释的开源项目 ...

  6. 使用sqlyog连接阿里云rds数据库

    使用sqlyog连接阿里云rds数据库 查看rds云数据库的外网地址 查看本机ip地址 配置白名单 填写上本机的ip然后点击确认 设置数据库的账号和密码 建议设置成普通账号 普通账号记得配置权限 使用 ...

  7. 阿里ECS云服务器连接RDS数据库服务器小白图文详细教程(云企业)

    场景:购买了一个ECS云服务器专门运行代码,再购买一个RDS数据库服务器专门放数据, 前提:我有两个阿里帐号A.B,两个帐号都购买了一个ECS服务器,分别是A-ECS1.B-ECS2:现在再购买多一个 ...

  8. 主数据库宕机怎么办?MHA高可用帮你实现主从服务器自动切换(详细操作与命令详解)

    一.MHA简介 上一篇介绍了MySQL的主从复制.读写分离,实现主从服务器同步的架构,它存在单点故障的隐患,一旦主服务器出现故障,将无法进行写入,为了解决这个问题,可以考虑是否能够让从服务器切换角色, ...

  9. 03 | AOF 日志:宕机了, Redis 如何避免数据丢失?

    文章目录 1. AOF日志是如何实现的 2. 三种写回策略 3. 日志文件太大了怎么办 4. AOF重写会阻塞吗? 1. AOF日志是如何实现的 AOF 日志是写后日志,"写后"的 ...

最新文章

  1. 关于xml的一些知识,DTD,XSD
  2. umi搭建react+antd项目(二)路由
  3. 用Kibana和logstash快速搭建实时日志查询、收集与分析系统
  4. Vue+G2:Please specify the container for the chart! + Cannot read property ‘appendChild‘ of null
  5. Linux与Windows文件查找命令
  6. 谱聚类、Chameleon聚类、PCCA、SOM、Affinity Propagation
  7. python关键字和保留字_或带有Python示例的关键字
  8. leetcode 477. 汉明距离总和(位运算)
  9. 沉淀一年零八个月,我也拿到了博客专家
  10. 阿里Java研发工程师实习面经
  11. redhat 7.2更新yum源时踩的坑
  12. [python] 在指定目录下找文件
  13. winsock类型病毒后遗症处理
  14. 第三节 UNIX文件系统结构
  15. 超低功耗高性能2.4GHz GFSK 无线收发芯片Si24R1替代NRF24L01P
  16. Shopee平台,对接运营经理是一条离成功更近的捷径
  17. 时间序列的距离度量DTW
  18. 下载维基百科wikipedia!
  19. 读书 | 少有人走的路心智成熟的旅程读后感
  20. 什么是 ECC 内存?(memory with ECC)

热门文章

  1. Unity3D关于ComputeShader
  2. Android 仿美拍,秒拍 ,视频封面选择.有图有真相.
  3. 上面两点下面一个三角形_【知识点】三角形全等的判定+性质+辅助线技巧都在这里了!...
  4. 云和恩墨大讲堂-Thinking in SQL,这是一次烧脑的课程
  5. Error opening data file Tesseract-OCR\tessdata/eng.traineddata问题 解决
  6. 8.0之后关闭个人热点功能实现
  7. UVA The Sultan's Successors
  8. 【Python性能优化实例】计算 numpy 数组首尾为 0 的数量
  9. unity小游戏的脚本
  10. 照片生成3D虚拟数字人,虚拟形象主播搭建(软件+教程)