可以進入互聯網相關公司作開發工做的,或多或少都瞭解分佈式擴容等內容,或者從書本上學到,或者從博客中找到。但到用的時候卻不多考慮之後怎麼擴容,怎麼更方便的擴展。本文結合我在實際工做中碰到的擴容的狀況進行實例說明。redis
說個現實一點兒的現象,在新項目初期基本上不考慮之後怎麼擴容誰去擴容的問題,某次其餘組的一個同窗問我:願哥,咱們有個線上的業務須要擴容,怎麼辦?我問他採用什麼方式分片的,他告訴我hash取模。我頭暈,這。。。沒啥好辦法,只能停服。若是不能停服,只能用雙寫移庫的方法。算法
之後再考慮擴容?session
這是典型的不負責任的表現,以我這幾年對項目的觀察看,通常擴容發生在兩年後,而新項目若是還算成功的話,第一年基本上該拿的獎基本上都拿了,該被確定的也被確定了。第三年的時候,主程還在不在還很差說,大多數項目的初期開發者都離職了。而沒有離職的都把項目轉手給其餘人了,而其餘人用1周解決,仍是用兩個月解決不關最初設計者的事情了。固然,若是是dau成直線上升的項目除外,這種項目最考驗初期架構師的能力,若是設計很差,真的會坑本身。架構
爲何後期後期難重構?運維
業務是延續的,若是是一個重要的業務,確定是不會停掉,給你留下慢慢的搞的時間,老闆的指望是你可以當即解決問題。這時你說,初期沒考慮擴容。。。我剛來北京的時候,當時作農場項目的兩個公司就是,一樣的項目,一樣的DAU爆發式增加。一個公司的項目由於難以擴容,結果在一週以後全部用戶都走光了,而另一個公司由於初期架構方便擴容,開啓了輝煌的一章。分佈式
雙寫移庫,實際上是我認爲一種比較low的懶惰的方法,是讓別人接坑的方法。說下特色:ide
1. 影響接口速度,雙寫無疑會增長調用redis的次數,增大時間,提升錯誤率。優化
2. 週期,從4個庫,移動幾百G的數據,在線上 用多長時間,開着飛機換輪子是否會形成出現誤差。在以前給某業務導數據過程當中,掛死過一個redis,致使線上的業務出現問題。ui
那麼程序設計之初就要有明確的目標:spa
1. DBA若是能在提供固定實例端口的基礎上,內容消化擴容,那麼問題就好辦了,也就沒有如下內容。
咱們曾經碰到過一種case,DBA提供了4個端口,而後經過內部中間件實現,然而,大約兩年事後,中間件維護者離職了,此方法就再也沒有人維護了。而後3年後,DBA說單臺機器空間打滿了,須要擴容。此時接收的RD滿滿都是淚。
2. 你存儲的信息是什麼,根據不一樣的內容實際上是有不一樣的方案的,若是存共享session這類臨時數據,那麼無疑一致性hash是最好的解決方案,運維增長一臺機器或者減小一臺機器,頂多會形成,一部分用戶從新登陸下,不會形成其餘問題。
而若是存儲的用戶信息,是不能隨便增長節點和減小節點的,由於任何變更都會引發用戶信息的丟失,這種丟失不可逆,不能經過從新登陸解決。此時,對於你採起 一致性hash,取模,或者區間算法實際是相同的。
3. 擴容:擴容的目標應該是,解決問題而又線上業務沒有問題,這個應該最高優先的目標。也就是,優化是程序架構側的事不是產品層面的事,不該引發系統服務的波動。
一致性hash
有些時候仍是須要客戶端在代碼中進行hash,這時候選擇hash算法尤其重要。有些項目中,架構師用了一致性hash算法作分庫分表,其實真的沒有考慮後期縮容和擴容的問題。
一致性hash算法主要解決的是從N到N-1的問題。
結合redis的集羣架構槽指派思路,我在某個項目中使用了區間算法,理由以下:
1. 由一個簡單的算法如md5 (uid) 取得最後兩位,哈希到00-FF共計256個節點,假設分配以下:00-3F 40-7F 80-BF C0-FF 分別對應4個redis實例A B C D。此時若是4個redis滿了,想盡快增長端口解決問題。能夠2中的步驟。
2. 對於00-3F的數據,能夠摘取一個從庫,單獨最爲主庫。如A A1, 此時A和A1中的數據是同樣的。而後修改配置 00-1F到A上面, 20-3F到A1上面,這樣就完成了擴充端口。
而後再寫一個腳本,線下刪除A裏面根據算法落到20-3F的數據,A1裏面根據算法落到A的數據。這樣,應該會很快的刪除到制定大小,無疑刪除數據遠大於移動寫入數據的速度。
Redis集羣架構
某項目一致性hash的算法示意圖:
區間算法示意圖:
總之,當你選擇服務的時候,你會選擇一種在你擴容的時候對線上有影響,仍是一種靠線下努力,按照步驟對線上沒影響的擴容方案呢。