1. 程式人生 > >Redis的KEYS命令引起宕機事件

Redis的KEYS命令引起宕機事件

Redis的KEYS命令引起RDS資料庫雪崩,RDS發生兩次宕機,造成幾百萬的資金損失

本文經授權轉載,僅用於學習,版權歸原作者所有。

最近的網際網路線上事故發生比較頻繁,2018年9月19號順豐發生了一起線上刪庫事件,在這裡就不介紹了。

在這裡講述一下最近發生在我公司的事故,以及如何避免,並且如何處理優化。

間接原因還有很多,技術跟不上業務的發展,由每日百萬量到千萬級是一個大的跨進,公司對於系統優化的處理優先順序不高,技術開發人手的短缺

第一次宕機

2018年9月13號某個點,公司某服務化專案的RDS例項連線飆升,CPU升到100%,拒絕了其他應用的所有請求服務

整個過程如下:

  • 監控報警,顯示RDS的CPU使用率達到80%以上,DBA介入,準備KILL慢SQL
  • 1分鐘內,沒有發現明顯阻塞的SQL,CPU持續上升到99%
  • 5分鐘內,大量應用報警,並且拒絕服務,RDS的監控顯示出現大量慢SQL,聯絡伺服器資料庫提供商進行協助
  • 8分鐘內,進行資料庫主備切換(業務會受損,但是也沒辦法,沒有定位到問題)
  • 9分鐘內,部分業務恢復,但是一些業務訂單的回撥訊息堆積超過20w,備庫的CPU使用率也持續上升
  • 15分鐘內,備庫CPU使用率超過97%,業務再次中斷,進行切回主庫,並進行限流
  • 20分鐘內,關閉一些次要應用的流量入口
  • 25分鐘內,主庫CPU使用率恢復正常
  • 30分鐘內,逐步開啟關閉的限流應用
  • 35分鐘內,所有應用恢復正常
  • 接下來就是與伺服器資料庫提供商成立應急小組緊急優化可能出現的慢SQL,雖然說可能解決了一些慢SQL,但此次並沒有定位到具體的問題,也就為幾天後再次發生宕機事件埋下了伏筆

事故影響

某服務化專案服務不可用幾十分鐘,造成訂單數減少幾十萬筆,損失百萬資金。

原因分析

當時是沒有定位到具體的原因的,但是下面的原因也是一部分可能引起宕機的情況。

某服務化專案的業務增速非常快,在高峰期,資料庫QPS突破35000,系統處於高負荷狀態。

在高峰期如果同時執行幾個全表掃描的SQL,會造成資料庫壓力急劇上升,應用超時增多,前端應用超時,使用者重試,流量飆升,形成了雪崩效應。

主要原因在與一些老專案的SQL查詢效能較差,並且使用的主庫,對資料庫影響較大。資料庫QPS太高,但是快取方案因為人手原因一直沒有落地,慢SQL的問題處理優先順序應該提升

改進方案

  • 針對每個應用建一個數據庫賬號,嚴格按照規範使用
  • 快取優化方案即時落地,慢SQL問題優先處理,集中處理目前已經發現的慢SQL(查詢時間超過1S)
  • 升級資料庫配置
  • 遷移非核心業務到新的RDS例項中去

第二次宕機

由於上一次的宕機原因未找到,所以此次的宕機是可以預見的。

2018年9月19號,還是一樣的"配方",還是原來的"味道"。同一個RDS,CPU飆升至100%,接下來就是拒絕服務,宕機。當然,有了第一次的經驗,直接主從切換,在幾十秒左右就恢復了所有業務,但還是嚴重影響了公司的業務和形象。

原因分析

恢復業務後,公司緊急召開了緊急事故研究會議,當然,我的級別是參與不了的。公司的高管,高層技術架構、DBA、各個專案的主負責人一起進行了會議。

在此次會議中,經過檢視各個專案的日誌,後臺的監控資料,發現在那臺RDS資料庫CPU飆升時,有一臺Redis資料庫記憶體將近100%,然後急劇下降。聯絡第一次的宕機情況,也是類似的。

接下來就是聯絡伺服器資料庫提供商,將那臺Redis最近一週的命令全部調用出來,最後發現,在那個時間點運行了一條keys *...*命令。公司的一個工程師執行keys模糊的匹配命令是為了清理沒用的鍵,但是沒有考慮到keys *進行模糊匹配引發Redis鎖,造成Redis鎖住,CPU飆升,引起了所有呼叫鏈路的超時並且卡住,等Redis鎖的那幾秒結束,所有的請求流量全部請求到RDS資料庫中,使資料庫產生了雪崩,使資料庫宕機。

改進方案

  • 所有線上操作,全部要經過運維通過後方可執行,運維部門逐步快速收回各項許可權
  • 新增Redis例項,進行分離
  • 如果有使用類似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資訊。客戶端連線儘量使用連線池(長連結和自動重連)。

關於Fundebug

Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了6億+錯誤事件,得到了Google、360、金山軟體等眾多知名使用者的認可。歡迎免費試用!

在這裡插入圖片描述

相關推薦

Redis的KEYS命令引起事件

Redis的KEYS命令引起RDS資料庫雪崩,RDS發生兩次宕機,造成幾百萬的資金損失 本文經授權轉載,僅用於學習,版權歸原作者所有。 最近的網際網路線上事故發生比較頻繁,2018年9月19號順豐發生了一起線上刪庫事件,在這裡就不介紹了。 在這裡講述一下最近發

怎樣最小化雲事件的影響?

高可用 隱私 而是 管理 flood 最小 流量 文件 最好的 雲計算並不是天生就是不可靠的,但是如同所有的IT形式一樣,必須仔細挑選和管理雲服務以實現特定的可靠性和可用性目標。這些步驟可以是合同形式的、是技術形式的或者甚至可能需要重新思考你的應用程序架構。如果沒有經過慎重

由Redis的hGetAll函式所引發的一次服務事件

昨晚通宵生產壓測,終於算是將生產服務宕機的原因定位到了,心累。這篇部落格,算作一個覆盤和記錄吧。。。   先來看看Redis的快取淘汰演算法思維導圖: 說明:當實際佔用的記憶體超過Redis配置的maxmemory時,Redis就會根據使用者選擇淘汰策略清除被選中的key。  

DigitalOcean事件回顧:主資料庫被刪除,四小時後恢復

在運維派前面文章中已經報道了 DigitalOcean宕機 的事故,今天將DigitalOcean的官方公告來了解整個事件的詳細過程: 事件回顧 2017年4月5日,DigitalOcean的控制面板與API遭遇時長4小時56分鐘的不可用狀態。在此期間,全部執行中的Droplets仍繼續正常運轉,

關於指標越界,指標亂指,等引起除錯方法

————彭曉林QQ:196568501 (歡迎交流)注:此方法適合於有規律的宕機問題。        在大家寫程式時候,特別是C語言開發時大家或多或少的都遇到過指標錯誤引起的宕機問題。    除錯的基本原理:指標錯誤引起的宕機,主要都是指標指向的地址,不是程式設計師所期望的地

Redis的KEYS命令引起RDS數據庫雪崩,RDS發生兩次,造成幾百萬的資金損失

千萬 monit 重構 情況 數據結構 all 顯示 十分鐘 string類 最近的互聯網線上事故發生比較頻繁,20180919順豐發生了一起線上刪庫事件,在這裏就不介紹了。 在這裏講述一下最近發生在我公司的事故,以及如何避免,並且如何處理優化。 間接原因還有很多,技術跟不

Redis 的 KEYS 命令引起 RDS 資料庫雪崩, 2 次,造成幾百萬損失

在這裡講述一下最近發生在我公司的事故,以及如何避免,並且如何處理優化。 該宕機的直接原因是使用 Redis 的 keys * 命令引起的,一共造成了某個服務化專案的兩次宕機。 間接原因還有很多,技術跟不上業務的發展,由每日百萬量到千萬級是一個大的跨進,公司對於系統

Redis的KEYS命令引起RDS資料庫雪崩,RDS發生兩次,造成幾百萬的資金損失

最近的網際網路線上事故發生比較頻繁,20180919順豐發生了一起線上刪庫事件,在這裡就不介紹了。 在這裡講述一下最近發生在我公司的事故,以及如何避免,並且如何處理優化。 該宕機的直接原因是使用Redis的keys *命令引起的,一共造成了某個服務化專案

weblogiccrash問題解決分享

優化 start .get 誤報 問題 article abort pro outside 近期比較煩躁。系統頻繁出現宕機。weblogic控制臺打印出例如以下內容: # Afatal error has been detected by the Java Runti

服務器壽命周期內只會關機一次,為什麽能夠長時間持續工作而不

電源 以及 商業 硬件 著名 使用方式 導致 性能問題 故障 首先,服務器能夠長時間持續的工作是和其硬件架構及使用環境相關的。 排名第一中提到的火星探測器其實使用的也是IBM P series服務器,並且在探測器裏搭載了兩臺,以實現HA冗余。 生活中的商用服務器為了能夠

mahout demo——本質上是基於Hadoop的分步式算法實現,比如多節點的數據合並,數據排序,網路通信的效率,節點重算,數據分步式存儲

fin urn [] return uid content 3.0 stock blank 摘自:http://blog.fens.me/mahout-recommendation-api/ 測試程序:RecommenderTest.java 測試數據集:item.csv

一例mysql主從數據庫,從庫後無法啟動的解決方案

mysql starting 啟動時報錯信息: Starting MySQL... ERROR! The server quit without updating PID file (/usr/local/mysql/data/qkzhi-appzookeeper-1.novalocal.pid

Linux服務器、數據丟失如何進行數據恢復

超級 完整 專業 數據分析 重要 .tar.gz 操作 公司 打開 [數據恢復故障描述]一臺linux網站服務器,DELL R200,管理約50個左右網站,使用一塊SATA 160GB硬盤。正常使用中突然宕機,嘗試再次啟動失敗,將硬盤拆下檢測時發現存在約100個壞扇區。某數

Mysql DBA 高級運維學習筆記-一主多從從庫切換主繼續和從庫同步過程

復制 導入數據 之間 pro vim 庫服務器 chan mas 優點 1.主庫master 宕機 登錄從庫show processlist\G 看兩個線程的更新狀態 mysql> show processlist\G ************************

雲計算之路-阿裏雲上:重啟 manager 節點引發 docker swarm 集群

node bili body 運行 nodes 服務 徹底 解決 ability 為了迎接春節假期後的訪問高峰,我們今天對 docker swarm 集群進行了變更操作,購買了1臺阿裏雲4核8G的服務器作為 worker 節點,由原來的 3 manager nodes +

雲計算之路-阿裏雲上:3個manager節點異常造成 docker swarm 集群

線索 logs 遇到 log 我們 控制臺 之路 服務 cnblogs 今天 11:29 - 11:39 左右,docker swarm 集群 3 個 manager 節點同時出現異常,造成整個集群宕機,由此給您帶來很大的麻煩,請您諒解。 受此次故障影響的站點有:博問,閃

redis集群節點

div 強一致 clust info post 超過半數 mage 在一起 情況下 redis集群是有很多個redis一起工作,那麽就需要這個集群不是那麽容易掛掉,所以呢,理論上就應該給集群中的每個節點至少一個備用的redis服務。這個備用的redis稱為從節點(slave

Git服務器如何使用本地克隆倉庫快速恢復Git服務器

git 代碼庫 分布式在工作中難免會出現代碼倉庫不能使用如:服務器磁盤跪了,高可用失效,地區級別的網絡癱瘓,等等。之前也聽過Git的一大亮點為去中心話的可靠代碼倉庫,那麽問題來了:代碼庫真的宕機了,連不上了,在短時間內需要團隊開發合並代碼,協作開發,發布版本,筆者在網上搜索一圈沒有人寫過類似文章(也有可能大家

ORA-0402導致oracle11gADG備庫問題處理

ADG ORA-4021 發現數據庫告警,查看alert日誌,發現如下報錯Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl1/trace/orcl1_lgwr_26383.trc:ORA-04021: timeout occurred while

esxi開啟命令行模式以及命令開啟虛擬

命令行、VMware在esxi界面按F2登錄選擇troubleshooting options選擇enable esxi shell返回登錄時的界面然後按alt+F1 從命令行啟動虛擬機:1、用命令列出虛擬機的ID:vim-cmd vmsvc/getallvms |grep <vm name>