當前位置:
首頁 > 最新 > Redis探索之路

Redis探索之路

1. 寫在前面

對於Redis相信各位程序猿童鞋都是不陌生的。這款使用ANSI C編寫的,基於內存亦可持久化的資料庫已經成為後端數據緩存炙手可熱的首選。但Redis自身的短板也被大家所詬病,例如:在現今動不動就24核32核的伺服器,Redis單線程的設計就無法利用好CPU資源;基於內存Redis在內存使用量巨大時,管理和維護顯得十分困難和低效等。相信聰明的童鞋們一定會想到通過單機多實例Redis然後採用客戶端分片的模式的方式解決上面的問題,確實這也是常見的方案。今天將給大家講講我們在這方面上的心路歷程~

2. 最開始的Redis

Redis最早在我們線上的正式應用是一款兒童遊戲。當時的遊戲數據存儲採用MySQL。資料庫做了20個分庫,存儲也做了RAID陣列,遊戲在線量較大時,資料庫的IO壓力依然非常大。為了減輕MySQL的壓力,我們採用Redis對數據做了緩存,這也是我們在線上的第一次嘗試這款nosql的新貴。

作為早期的架構方案設計也比較簡單,就是四台伺服器構成兩組Redis主從的模型:

單機內存32G,開20個Redis實例。

主庫不做AOF,也不做快照,每天凌晨定時做快照並異地遷移,從庫開啟AOF並1秒落地。

主庫每5分鐘插入一個時間點,方便從庫AOF記錄時間點,用於定點還原。

雖然架構簡單不過確實極大地緩解了MySQL的壓力,但弊端也開始顯露:如果主Redis掛了,則藉助從庫手動做定點還原,還有程序層面涉及的一系列操作。而且故障無法自動轉移,在線高時故障會給用戶帶來相當不好的體驗,更不提運維攻城獅自己的苦逼了。

如果能實現故障自動轉移,那也是極好的。那時年少,對未來充滿了期待。

3. Redis sentinel的出現

業務高可用、故障自動轉移一直是咱們運維攻城獅極力追求的。我們也是一步一個腳印地前進,努力往這目標邁進,大家有興趣有閱讀本公眾號之前的文章《雙機房災備架構搭建實踐》。

隨著業務的發展,Redis開始越來越多地被我們所使用。尤其是在公共平台Redis幾乎就是緩存的不二之選,同時對Redis故障自動轉移的需求也越來越迫切。於是我們一開始採用官方推薦的Redis實例的監控管理工具:Redis-sentinel。

3.1 Redis sentinel剖析

Sentinel是多個Redis實例的監控管理工具,主要實現以下三個功能:

Monitoring: Sentinel 會不斷地檢查主Redis和從Redis是否運作正常。

Notification: 被監控的某個 Redis出現問題時,Sentinel 可以通過 API發送通知。

Automatic failover: 當主Redis不能正常工作時, Sentinel 會自動進行故障遷移操作,將Redis主從的角色進行互換。

3.2 Redis sentinel應用

Sentinel第一次在線上的應用是一款公共社交平台。

Redis用於DB緩存,通過同內網伺服器搭建Redis主從模型,實現主Redis讀寫、從Redis落地。藉助Sentinel的Automatic failover,主Redis故障時,自動切換Redis主從。我們的設計方案如下:

從上圖可以看出,程序讀寫Redis都是通過VIP實現的。Keepalive藉助vrrp_script檢測當前Redis master是否異常以決定是否轉移VIP,Sentinel實現故障時主從自動切換。Redis master不備份,定時腳本每晚檢查當前Redis是否為slave,然後進行bgsave。由於設計為互備,主從故障切換後可以不進行回切。

Sentinel + keepalive在實現Redis故障轉移這塊確實幫了我們很大的忙,但在實際應用時也需要遇到了以下問題:

Sentinel存在網路分區的問題,會受到網路影響造成誤判。

當面對業務規模較大,甚至需要進行擴容時,Sentinel的功能就顯得有些捉襟見肘。

Keepalive的VIP切換存在約40ms延遲,程序設計前期需要考慮網路鏈接的異常處理。

4. Redis cluster踐行

4.1 Redis cluster窺視

Redis cluster是一個去中心化、多實例Redis間進行數據共享的集群。由於被設計為無中心節點和無代理節點,Redis cluster可以實現集群節點的在線線性伸縮,並通過主從複製模型來提供一定程度的高可用行,在實際環境中某個節點故障不可用時,集群其他節點可以持續提供服務。

關於數據分片,Redis cluster並沒有採用一致性hash,而是引入了hash slot。整個集群共有16384個slot,這些slot被全部分配在各個節點中,並且可以在不同節點間遷移。而每個slot存放哪些數據是由key通過CRC16校驗後對16384取模來決定的。

為了使集群中部分節點故障或者失去聯繫的情況下集群其他節點可以提供持續服務,Redis cluster 採用主從複製模型。簡單的說,就是每個對外提供服務的節點,我們稱之為master節點,並為每個master節點提供一個slave節點。當其中一個master節點故障時,其slave節點替代原有的master節點,以保證不會因為找不到slot而使整個集群不可用。

4.2 Redis cluster應用

Redis cluster所具備的水平伸縮能力和高可用性開始逐漸被我們業務所青睞。

Redis cluster目前主要應用於後端大數據平台,常見配置都是藉助高配機部署4個8G內存的Redis實例組建4個master節點的集群,必要時直接通過同內網物理機擴容節點即可,非常方便。在需求量比較大的場景,比如我們的雲推送平台,更是藉助96G內存的超配機部署單實例10G的集群。下圖是其中一個實例內存使用情況:

在後端業務的架構中,由於Redis處於緩存層,藉助cluster-require-full-coverage參數,允許我們的集群一個節點故障而業務依然可以正常運行,因此在設計上,我們取消了slave節點,將所有實例都成為master。

運維、開發以及業務方積極的溝通協作,加之集群靈活的伸縮能力,讓我們可以在業務高峰來臨前及時擴容集群,無縫平滑對業務提供支持,在業務量減小時,可以做必要的集群收縮。及時的擴容、必要的收縮既是為了保障業務持續穩定,也是為了合理高效地利用資源。

5. Redis cluster實踐

說了這麼多,相信大家並不滿足於理論性的介紹。筆者就給大家講解Redis cluster的實踐方式。

我們通過四個Redis實例構成集群。注意:Redis cluster需要3.0以上的版本。限於邊幅Redis部署過程就略去了,下面是集群每個節點需要的配置:

5.1 創建集群

使用redis-trib.rb命令的create選項來創建四個master節點的集群,命令如下:

使用redis-trib.rb命令的check選項來瞄一眼剛剛創建的集群:

可以看到四個節點在集群中的角色都是master,並且每個節點都持有4096個slot。

5.2 伸縮集群

現在我們模擬一個情景:線上業務壓力劇增,現有的集群壓力巨大,我們需要對集群進行擴容並且不中斷業務。

在開始之前,我們在後台跑個小腳本,讓它不間斷對集群寫入數據:

新增節點可以使用redis-trib.rb 命令的add-node選項,命令如下:

目前Redis cluster還無法自動為新加入的加點分配slot,需要管理員手動分配,算是一個短板。使用redis-trib.rb 命令的reshard選項,給新節點分配100個slot吧,命令如下:

上面這條命令很easy,從$ 節點遷移100個slot到$節點的。我們來看看命令的執行結果:

如上圖,新增的master節點不僅擁有了100個slot,同時還有數據。這也就說明了,slot的遷移其實也就是數據的遷移。

也許童鞋們覺得筆者很摳門,新的master節點才給100個slot。沒關係redis-trib.rb命令的rebalance選項可實現slot在所有節點間均衡分配,這裡就不做贅述了,就留給大家當做課後作業。

現在讓我們來試試將集群收縮吧。假設業務已經平穩度過高峰期,4個節點完全能扛得住壓力,需要去掉6005這個節點。

將一個節點從集群中剔除,首先要做的是將該節點的數據遷移至集群其他節點,也就是slot全部轉移到集群其他節點。Slot遷移通過上面的介紹大家都知道通過redis-trib.rb命令的reshard選項來實現,就不再複述了。6005節點的slot都遷移到6004節點,得到的結果應該是:6005節點「0 keys 0 slots」。

其次使用redis-trib.rb命令的del-node選項來將節點從集群中去除,命令如下:

看看效果:

至此我們就完成了一次集群的收縮工作。

童鞋們注意:對集群進行擴容收縮的工作,實際就是對slot的遷移,意味著進行數據遷移,過程挺消耗性能的,因此建議大家及時根據業務趨勢提前做好評估和規劃工作,避免在高峰時段給伺服器增加額外的壓力。

5.3 健壯集群

如前面描述Redis cluster採用主從複製模型來避免個別節點故障失聯而導致集群不可用。相信這會是各位童鞋最期待的。

依舊是啟用一個新的Redis6005實例,為6004節點增加一個slave節點,命令如下:

我們看看此時的集群狀態:

看圖中紅框框的部分,這裡表明了他倆是一對master/slave 。

現在failover掉6004節點(ps:進行failover節點必須是slave節點):

將6004節點failover後,6005應該提升為master節點替代6004,來看看現在的集群節點是不是如我們預期的:

從上面的信息可以看出,原有的master 6004已經降級為slave,而6005則升級為master替代6004,並且集群可以持續正常服務:

同理如6004節點恢復了,可在6004節點上執行cluster failover命令,讓6005節點假故障,實現主從切換,恢復原有的集群狀態。

線上的配置規劃,如果伺服器資源充裕的話,還是建議為每個master節點都配置slave,防止節點意外故障而導致集群無法使用。當然要是資源吃緊,也是可以在某些敏感時段進行臨時配置slave,畢竟Redis cluster的伸縮都是很靈活的。

6. 結束語

以上就是我們在Redis上走過的路,相信會對大家對使用Redis上有幫助。技術選型其實並不是運維一言拍板,而是結合業務需求協調開發的基礎上確定方案,並在業務程序開發前與開發者溝通注意事項。任何技術都有其優劣的方面,詳細了解、提前規避風險、針對自身業務做好規劃才是正確使用技術的方式。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 運維軍團 的精彩文章:

TAG:運維軍團 |