背景
先澄清一下,整個程序問題都不是我解決的,我在里面就是起了個打醬油的角色,因為實際上我負責這個專案,整個程序也比較清楚,之前也跟具體負責的同事說過,等過段時間帶他做做專案復盤,結果一直忙,之前做的事情都快忘了也沒帶他做復盤,所以趁著還記得,總結一下這個問題,也算一起做個復盤總結了,
本周一的時候,我們測驗環境遇到一個問題:啟動一個服務就會導致后端呼叫耗時增加,當時咨詢了對這個問題之前有了解的同事得到的答復是因為一筆請求發到兩套測驗環境(一個請求需要在兩套環境下運行結果做對比),因為這兩套環境共用同一套redis集群,收到第二個相同請求的時候,會將這筆請求標記為重復請求,下游接收到這筆請求是重復的,需要重新查詢資料庫驗證請求是否重復,不是的話做一個糾正,所以這時候會造成請求延遲升高,
負責解決這個問題的同事小A就問我:那是不是再搭建一套將兩套Redis集群分開就解決了,我說不一定,還有解釋不通的地方:一個環境服務不啟動不寫redis,另一個環境服務啟動寫redis的時候也會遇到這個問題,
于是小A找了這個服務相關負責的同事了解業務,因為測驗環境的總責任人是我,所以了解業務的時候,小A也把我拉了一起了解,通過同事的講述了解到一個環境中服務要寫兩個機房,如果兩個機房的Redis是同一套也會被標記成重復請求,
至此,解決環境問題的方法有了答案:每套環境要搭建兩套Redis集群,兩個環境4套Redis集群來解決問題,
往往,一個答案只是一系列問題的開始,
時間線
我們的搭建方案是直接在使用Redis的服務上搭建連接它的兩套Redis集群,只改下埠,多跑兩個行程,
問題1:服務器退出登錄Redis服務會停止
小A告訴我遇到問題的現象:按照網上經典的安裝啟動教程,啟動成功了,但是當干會兒別的,ssh自動退出登錄之后再看Redis服務就停止了,
我聽到這里首先想到的是這個現象基本可以斷定是以非daemon行程在運行,于是我上網上找了以deamon方式運行的命令發給小A:
redis-server ./redis.conf --daemonize yes
小A看了解決方法補充到那一定也可以在組態檔里直接配置daemon方式運行,我表示贊同,他也是這么做的,我當時沒有點破,相信剛畢業的他不久也自己會發現組態檔和顯示命令實際上是一回事,只是一個是永久生效,一個是每次運行時生效,而直接用這條命令只是為了說明本質問題,
問題2:服務連接Redis報錯Not Auth
小A又向我反饋報了一個錯,說他在網上查的是Redis版本問題,估計需要重新搭建Redis,我過去看了一下:Redis集群是3.X的版本,jedis客戶端用的是2.9的版本,沒有聽說過Redis3.X的版本有不向下兼容的問題,同時因為這個Redis是從負責Redis的團隊要過來的安裝包,應該和現在跑著的是一個版本,如果懷疑Redis的團隊發的安裝包與之前不一樣的話,我也確信之前肯定版本不會低于3.0,因為Redis是從3.0之后才支持集群的,所以我判定不是Redis版本問題,讓他再查查,實際上我的意思是讓他換關鍵詞來查,比如可以按照報錯的提示原因來查,也可以按照例外來查,不同的關鍵詞搜索可以獲得不同的資訊,
然后我看了報的錯:其他的沒細看,只見赫然寫著:Not Auth,我就問:Redis服務有沒有設定密碼,他說沒有,還演示了一下,我在旁邊確認了沒有,就查看客戶端配置有沒有配置密碼,果然客戶端里有密碼配置,這就與服務端不匹配了,
問題3:報錯cluster support disabled
小A將客戶端密碼去掉重新打包部署之后,Not Auth的錯不報了,但是其實報了兩個錯,還有一個錯沒解決:就是提示cluster support disabled,
我說集群方式啟動應該就是一個配置,應該有個cluster-enabled什么的從no改成yes,我還出了個餿主意(注意這里用到的餿主意,想想《紅樓夢》里每句話都是劇透,這里也不例外):我說理論上一臺集群也可以算一個集群,應該可以直接改個配置就以集群方式啟動了,
小A按照我說的思路用直接改配置為集群的方法,客戶端再啟動果然沒有報錯了,
問題4:請求延遲沒有好轉,Redis服務端沒有寫入成功資料
客戶端沒有報錯之后,小A重試原問題現場,請求延遲沒有好轉,另外,還發現Redis服務端沒有寫入成功的資料,
這次我和小A首先一起排查配置有沒有配置對,發現配置沒有問題,我就跟小A說:讓他多打日志,客戶端連接的地方打一些,讀寫資料的地方打一些,
通過這個方法,小A定位到客戶端連接的連接池為空,最終自己排查到是一臺機器的集群的哈希槽在一臺機器情況下哈希槽分配有問題,資料寫入失敗,最后每個集群多起了2個Redis行程做成3個節點的集群解決了問題,
可優化的排查思路分析
在問題4排查的時候,我和小A一起檢查了配置是否正確來確認Redis請求是請求到了正確的服務端,其實,有個更為直接和說明問題的方法:抓包,可以tcpdump埠查請求流量是不是正確從客戶端發出來了,被轉發到了哪里,
在《技術方案設計的方法》里我也提到,很多時候搜索不到自己想要的資訊很可能是關鍵詞的問題,排查問題的時候也可以試著換換關鍵詞來搜索,
根本原因分析
這里面有個問題沒有徹底搞清楚:為什么一臺機器的Redis集群會有問題,
問了小A,當時例外時getSlots方法時回傳了空,就是說問題實際上可能是slot沒有被分配,
我就問他單臺機器的時候有沒有在redis-cli客戶端上運行cluster info命令,他給我發了下面的運行情況截圖,

這張截圖驗證了我的猜想,slot沒有被分配,集群狀態為失敗,所以連接不上,
那需要連接上的條件并非是集群里有幾個節點,而是slots分配,集群狀態成功,

為了驗證這個猜想,我搭建了一個一個節點的集群,手動cluster addslots了0到16383個slot,集群判斷16384個slot都分配完畢,自動狀態改成OK,
這整個程序說明了:網上都是說Redis集群必須是3個節點以上的最好是單數個節點來啟動,單數個節點是為了投票的時候可以三局兩勝得出結論:一半以上的節點掛掉整個集群不可用,而對于Redis根本上判斷集群是否可用是根據slot有沒有完整的16384個slot在提供服務決定的,
總結
我覺得在整個程序中小A的表現我覺得很OK的,有4點:
1>主觀能動性
在程序中,他自己通過網上搜素找資源,自己解決了很多問題,整個問題處理程序中其實沒花費我多少時間,花時間的事情他都自己解決了,
2>合理的利用了各種資源
對于業務不理解,他找了理解業務的同事,技術問題搞不定他找了我,因為我對專案負責,所以找我是很合情合理的,同時,我是很希望他遇到這種事情來找我的,因為他找我證明他是信任我的,相信我能一定程度幫到他,第二,他找我是把我當成一種資源,作為資源我被需要,是有價值的,被需要讓人覺得很踏實,
我在有搞不定的事情的時候也向上尋求幫助,比如之前需要其他組協作的時候人家有排期遇到困難,領匯出面幫忙搞定了,還有申請資源由于暫時性資源緊張,申請不到,也是更上級出面幫忙搞定了,一個稱職的上級一定可以成為一種資源,也愿意讓自己成為資源,但是成為資源的形式不同,有的可能提供的是戰略,有的提供的是精神支持等,
3>事后總結
問題解決后,小A有自己寫wiki總結事情經過,避免后人采坑,同時自身也有總結識訓,
4>及時溝通
中間程序中,他每個關鍵步驟都有及時跟我溝通,因為解決完后他反饋給我:他自己覺得對于redis原理還沒有理解,所以不清楚為什么3個節點就OK的原因,我因為了解他的想法,所以才自己又實驗給出一個根本原因分析,
關于Redis,就一句話:那些很多人說只有面試的時候才能用到的東西,我總是發現實際作業中很有用,
相關閱讀
MySQL常見6個考題在實際作業中的運用
Tair分布式快取
Elasticsearch實戰-磁盤IO被打滿
業務開發轉基礎開發,這三種「高可用」架構你會么?
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/242787.html
標籤:NoSQL
上一篇:SQL 排序檢索資料
下一篇:Mysql簡要概述
