关于大型站点技术演进的思考(七)--存储的瓶颈(7)
事實(shí)上無論什么樣的問題場景最后解決它都要落實(shí)到數(shù)據(jù)庫的話。那么這個問題場景一定是擊中了數(shù)據(jù)庫的某個痛點(diǎn),那么我前面的六篇文章里那些手段究竟是在解決數(shù)據(jù)庫的那些痛點(diǎn),以下我總結(jié)下,詳細(xì)例如以下:
痛點(diǎn)一:數(shù)據(jù)庫的連接數(shù)不夠用了。
換句話說就是在同一個時間內(nèi),要求和數(shù)據(jù)庫建立連接的請求超出了數(shù)據(jù)庫所同意的最大連接數(shù),假設(shè)我們對超出的連接數(shù)沒有進(jìn)行有效的控制讓它們直接落到了數(shù)據(jù)庫上,那么就有可能會讓數(shù)據(jù)庫不堪重負(fù),那么我們就得要分散這些連接。或者讓請求排隊(duì)。
痛點(diǎn)二:對于數(shù)據(jù)庫表的操作無非兩種一種是寫操作,一種是讀操作,在現(xiàn)實(shí)場景下非常難出現(xiàn)讀寫都成問題的事情。往往是當(dāng)中一種表的操作出現(xiàn)了瓶頸問題所引起的。因?yàn)樽x和寫都是操作同一個介質(zhì)。這就導(dǎo)致假設(shè)我們不正確介質(zhì)進(jìn)行拆分去單獨(dú)解決讀的問題或者寫的問題會讓問題變的復(fù)雜化,最后非常難從根本上解決這個問題。
痛點(diǎn)三:實(shí)時計(jì)算和海量數(shù)據(jù)的矛盾。本系列講存儲瓶頸問題事實(shí)上有一個范疇的,那就是本系列講到的手段都是在使用關(guān)系數(shù)據(jù)庫來完畢實(shí)時計(jì)算的業(yè)務(wù)場景。而現(xiàn)實(shí)中,數(shù)據(jù)庫里表的數(shù)據(jù)都會隨著時間推移而不斷增長,當(dāng)表的數(shù)據(jù)超出了一定規(guī)模后,受制于計(jì)算機(jī)硬盤、內(nèi)存以及CPU本身的能力,我們非常難完畢對這些數(shù)據(jù)的實(shí)時處理。因此我們就必需要採取新的手段解決這些問題。
我今天之所以總結(jié)下這三個痛點(diǎn),主要是為了告訴大家當(dāng)我們面對存儲瓶頸問題時候。我們要把問題終于落實(shí)到這個問題究竟是由于觸碰到了數(shù)據(jù)庫的那些痛點(diǎn)。這樣回過頭來再看我前面說到的技術(shù)手段,我就會知道該用什么手段來解決這個問題了。
好了,多余的話就講到這里,以下開始本篇的主要內(nèi)容了。首先給大伙看一張有趣的漫畫,例如以下圖所看到的:
?
身為程序猿的我看到這個漫畫感到非常沮喪,由于我們被機(jī)器打敗了。可是這個漫畫同一時候提醒了做軟件的程序猿,軟件的性能事實(shí)上和硬件有著不可切割的關(guān)系,也許我們碰到的存儲問題不一定是由我們的程序產(chǎn)生的,而是由于好的炮彈裝進(jìn)了一個老舊過時的大炮里,最后當(dāng)然我們會感到炮彈的威力沒有達(dá)到我們的預(yù)期。除此之外了,也有可能我們的程序設(shè)計(jì)本身沒有有效的利用好已有的資源,所以在前文里我提到假設(shè)我們知道存儲的瓶頸問題將會是站點(diǎn)首先發(fā)生故障的地方,那么在數(shù)據(jù)庫建模時候我們要盡量減輕數(shù)據(jù)庫的計(jì)算功能,僅僅保留數(shù)據(jù)庫最主要的計(jì)算功能。而復(fù)雜的計(jì)算功能交由數(shù)據(jù)訪問層完畢。這事實(shí)上是為解決瓶頸問題打下了一個良好的基礎(chǔ)。最后我想強(qiáng)調(diào)一點(diǎn),作為軟件project師常常會不自覺地忽視硬件對程序性能的影響。因此在設(shè)計(jì)方案時候考察下硬件和問題場景的關(guān)系也許能開拓我們解決這個問題的思路。
上面的問題按本篇開篇的痛點(diǎn)總結(jié)的思路總結(jié)下的話。那么就是例如以下:
痛點(diǎn)四:當(dāng)數(shù)據(jù)庫所在server的硬件有非常大提升時候。我們能夠優(yōu)先考慮能否夠通過提升硬件性能的手段來提升數(shù)據(jù)庫的性能。
在本系列的第一篇里。我講到依據(jù)http無狀態(tài)的特點(diǎn),我們能夠通過剝離webserver的狀態(tài)性主要是session的功能。那么當(dāng)站點(diǎn)負(fù)載增大我們能夠通過添加webserver的方式擴(kuò)容站點(diǎn)的并發(fā)能力。事實(shí)上無論是讀寫分離方案,垂直拆分方案還是水平拆分方案細(xì)細(xì)體會下,它們也跟水平擴(kuò)展web服務(wù)的方式有類似之處。這個類似之處也就是通過添加新的服務(wù)來擴(kuò)展整個存儲的性能,那么新的問題來了。前面的三種解決存儲瓶頸的方案也能做到像web服務(wù)那樣的水平擴(kuò)展嗎?換句話說。當(dāng)方案運(yùn)行一段時間后。又出現(xiàn)了瓶頸問題,我們能夠通過添加server就能解決新的問題嗎?
要回答清楚這個問題,我們首先要具體分析下web服務(wù)的水平擴(kuò)展原理,web服務(wù)的水平擴(kuò)展是基于http協(xié)議的無狀態(tài)。http的無狀態(tài)是指不同的http請求之間不存在不論什么關(guān)聯(lián)關(guān)系,因此假設(shè)后臺有多個web服務(wù)處理http請求。每一個webserver都部署同樣的web服務(wù),那么無論那個web服務(wù)處理http請求,結(jié)果都是等價的。
這個原理假設(shè)平移到數(shù)據(jù)庫,那么就是每一個數(shù)據(jù)庫操作落到隨意一臺數(shù)據(jù)庫server都是等價的,那么這個等價就要求每一個不同的物理數(shù)據(jù)庫都得存儲同樣的數(shù)據(jù),這么一來就沒法解決讀寫失衡,解決海量數(shù)據(jù)的問題了。當(dāng)然這樣做看起來似乎能夠解決連接數(shù)的問題,可是面對寫操作就麻煩了,由于寫數(shù)據(jù)時候我們必須保證兩個數(shù)據(jù)庫的數(shù)據(jù)同步問題。這就把問題變復(fù)雜了,所以web服務(wù)的水平擴(kuò)展是不適用于數(shù)據(jù)庫的。這也變相說明。分庫分表的數(shù)據(jù)庫本身就擁有非常強(qiáng)的狀態(tài)性。
只是web服務(wù)的水平擴(kuò)展還代表一個思想。那就是當(dāng)業(yè)務(wù)操作超出了單機(jī)server的處理能力。那么我們能夠通過添加server的方式水平拓展整個webserver的處理能力,這個思想放到數(shù)據(jù)庫而言。肯定是適用的。那么我們就能夠定義下數(shù)據(jù)庫的水平擴(kuò)展,詳細(xì)例如以下:
數(shù)據(jù)庫的水平擴(kuò)展是指通過添加server的方式提升整個存儲層的性能。
數(shù)據(jù)庫的讀寫分離方案,垂直拆分方案還有水平拆分方案事實(shí)上都是以表為單位進(jìn)行的,假如我們把數(shù)據(jù)庫的表作為一個操作原子。讀寫分離方案和垂直拆分方案都沒有打破表的原子性,而且都是以表為著力點(diǎn)進(jìn)行。因此假設(shè)我們添加server來擴(kuò)容這些方案的性能,肯定會觸碰表原子性的紅線,那么這個方法也就演變成了水平拆分方案了,由此我們能夠得出一個結(jié)論:
數(shù)據(jù)庫的水平擴(kuò)展基本都是基于水平拆分進(jìn)行的,也就是說數(shù)據(jù)庫的水平擴(kuò)展是在數(shù)據(jù)庫水平拆分后再進(jìn)行一次水平拆分。水平擴(kuò)展的次數(shù)也就代表的水平拆分迭代的次數(shù)。因此要談好數(shù)據(jù)庫的水平擴(kuò)展問題。我們首先要更加仔細(xì)的分析下水平拆分的方案,當(dāng)然這里所說的水平拆分方案指的是狹義的水平拆分。
數(shù)據(jù)庫的水平擴(kuò)展事實(shí)上就是讓被水平拆分的表的數(shù)據(jù)跟進(jìn)一步的分散,而數(shù)據(jù)的離散規(guī)則是由水平拆分的主鍵設(shè)計(jì)方案所決定的。在前文里我推崇了一個使用sequence及自增列的方案。當(dāng)時我給出了兩種實(shí)現(xiàn)手段。一種是通過設(shè)置不同的起始數(shù)和同樣的步長,這樣來拆分?jǐn)?shù)據(jù)的分布,還有一種是通過估算每臺server的存儲承載能力。通過設(shè)定自增的起始值和最大值來拆分?jǐn)?shù)據(jù),我當(dāng)時說到方案一我們能夠通過設(shè)置不同步長的間隔,這樣我們?yōu)槲覀冎蟮乃綌U(kuò)展帶來便利。方案二起始也能夠設(shè)定新的起始值也來完畢水平擴(kuò)展,可是無論哪個方案進(jìn)行水平擴(kuò)展后。有個新問題我們不得不去面對,那就是數(shù)據(jù)分配的不均衡。由于原有的server會有歷史數(shù)據(jù)的負(fù)擔(dān)問題。
而在我談到狹義水平拆分時候,數(shù)據(jù)分配的均勻問題曾被我作為水平技術(shù)拆分的長處。可是到了擴(kuò)展就出現(xiàn)了數(shù)據(jù)分配的不均衡了,數(shù)據(jù)的不均衡會造成系統(tǒng)計(jì)算資源利用率混亂,更要命的是它還會影響到上層的計(jì)算操作。比如海量數(shù)據(jù)的排序查詢。由于數(shù)據(jù)分配不均衡,那么局部排序的偏差會變得更大。解決問題的手段僅僅有一個。那就是對數(shù)據(jù)依據(jù)平均原則又一次分布,這就得進(jìn)行大規(guī)模的數(shù)據(jù)遷移了,由此可見,除非我們認(rèn)為數(shù)據(jù)是否分布均勻?qū)I(yè)務(wù)影響不大,不須要調(diào)整數(shù)據(jù)分布,那么這個水平擴(kuò)展還是非常有效果,可是假設(shè)業(yè)務(wù)系統(tǒng)不能容忍數(shù)據(jù)分布的不均衡,那么我們的水平擴(kuò)展就相當(dāng)于又一次做了一遍水平拆分。那是相當(dāng)?shù)穆闊J聦?shí)上這些還不是最要命的。假設(shè)一個系統(tǒng)后臺數(shù)據(jù)庫要做水平擴(kuò)展。水平擴(kuò)展后又要做數(shù)據(jù)遷移,這個擴(kuò)展的表還是一個核心業(yè)務(wù)表,那么方案上線時候必定導(dǎo)致數(shù)據(jù)庫停止服務(wù)一段時間。
數(shù)據(jù)庫的水平擴(kuò)展本質(zhì)上就是水平拆分的迭代操作,換句話說水平擴(kuò)展就是在已經(jīng)進(jìn)行了水平拆分后再拆分一次,擴(kuò)展的主要問題就是新的水平拆分能否繼承前一次的水平拆分。從而實(shí)現(xiàn)僅僅做少量的改動就能達(dá)到我們的業(yè)務(wù)需求。那么我們假設(shè)想解決問題就得回到問題的源頭,我們的前一次水平拆分能否良好的支持興許的水平拆分。那么為了做到這點(diǎn)我們究竟要注意哪些問題呢?我個人覺得應(yīng)該主要注意兩個問題。它們各自是:水平擴(kuò)展和數(shù)據(jù)遷移的關(guān)系問題以及排序的問題。
問題一:水平擴(kuò)展和數(shù)據(jù)遷移的關(guān)系問題。
在我上邊的樣例里,我們所做的水平拆分的主鍵設(shè)計(jì)方案都是基于一個平均的原則進(jìn)行的,假設(shè)新的server增加后就會破壞數(shù)據(jù)平均分配的原則,為了保證數(shù)據(jù)分布的均勻我們就不能不將數(shù)據(jù)做對應(yīng)的遷移。這個問題推而廣之。就算我們水平拆分沒有過分強(qiáng)調(diào)平均原則。或者使用其它維度來切割數(shù)據(jù),假設(shè)這個維度在水平擴(kuò)展時候和原庫原表有關(guān)聯(lián)關(guān)系,那么結(jié)果都有可能導(dǎo)致數(shù)據(jù)的遷移問題。由于水平擴(kuò)展是非常easy產(chǎn)生數(shù)據(jù)遷移問題。
對于一個實(shí)時系統(tǒng)而言,核心的業(yè)務(wù)表發(fā)生數(shù)據(jù)遷移是一件風(fēng)險非常大成本非常高的事情。拋開遷移的操作危急,數(shù)據(jù)遷移會導(dǎo)致系統(tǒng)停機(jī),這點(diǎn)是全部系統(tǒng)相關(guān)方非常難接受的。那么怎樣解決水平擴(kuò)展的數(shù)據(jù)遷移問題了,那么這個時候一致性哈希就派上用場了,一致性哈希是固定哈希算法的衍生,以下我們就來簡介下一致性哈希的原理,首先我看看以下這張圖:
?
一致性哈希使用時候首先要計(jì)算出用來做水平拆分server的數(shù)字哈希值,并將這些哈希值配置到0~232的圓上,接著計(jì)算出被存儲數(shù)據(jù)主鍵的數(shù)字哈希值,并把它們映射到這個圓上。然后從數(shù)據(jù)映射到的位置開始順時針查找,并將數(shù)據(jù)保存在找到的第一個server上,假設(shè)主鍵的哈希值超過了232,那么該記錄就會保存在第一臺server上。這些如上圖的第一張圖。
那么有一天我們要加入新的server了,也就是要做水平擴(kuò)展了,如上圖的第二張圖。新節(jié)點(diǎn)(圖上node5)僅僅會影響到的原節(jié)點(diǎn)node4。即順時針方向的第一個節(jié)點(diǎn),因此一致性哈希能最大限度的抑制數(shù)據(jù)的又一次分布。
上面的例圖里我們僅僅使用了4個節(jié)點(diǎn),加入一個新節(jié)點(diǎn)影響到了25%左右的數(shù)據(jù)。這個影響度還是有點(diǎn)大,那有沒有辦法還能減少點(diǎn)影響了,那么我們能夠在一致性哈希算法的基礎(chǔ)上進(jìn)行改進(jìn)。一致性哈希上的分布節(jié)點(diǎn)越多,那么加入和刪除一個節(jié)點(diǎn)對于整體影響最小。可是現(xiàn)實(shí)里我們不一定真的是用那么多節(jié)點(diǎn),那么我們能夠添加大量的虛擬節(jié)點(diǎn)來進(jìn)一步抑制數(shù)據(jù)分布不均衡。
前文里我將水平拆分的主鍵設(shè)計(jì)方案類比分布式緩存技術(shù)memcached。事實(shí)上水平拆分在數(shù)據(jù)庫技術(shù)里也有一個專屬的概念代表他,那就是數(shù)據(jù)的分區(qū),僅僅只是水平拆分的這個分區(qū)粒度更大,操作的動靜也更大,筆者這里之所以提這個主要是由于寫存儲瓶頸一定會受到我自己經(jīng)驗(yàn)和知識的限制,假設(shè)有朋友由于看了本文而對存儲問題發(fā)生了興趣。那么我這里也能夠指明一個學(xué)習(xí)的方向,這樣就能避免一些價值不高的探索過程。讓學(xué)習(xí)的效率會更高點(diǎn)。
問題二:水平擴(kuò)展的排序問題。當(dāng)我們要做水平擴(kuò)展時候肯定有個這種因素在作怪:數(shù)據(jù)量太大了。
前文里我說道過海量數(shù)據(jù)會對讀操作帶來嚴(yán)重挑戰(zhàn),對于實(shí)時系統(tǒng)而言。要對海量數(shù)據(jù)做實(shí)時查詢差點(diǎn)兒是件無法完畢的工作,但是現(xiàn)實(shí)中我們還是須要這種操作,但是當(dāng)碰到如此操作我們一般採取抽取部分結(jié)果數(shù)據(jù)的方式來滿足查詢的實(shí)時性。要想讓這些少量的數(shù)據(jù)能讓用戶愜意,而不會產(chǎn)生太大的業(yè)務(wù)偏差。那么排序就變變得十分重要了。
只是這里的排序一定要加上一個范疇,首先我們要明白一點(diǎn)啊。對海量數(shù)據(jù)進(jìn)行全排序,而這個全排序還要以實(shí)時的要求進(jìn)行,這個是根本無法完畢的。為什么說無法完畢,由于這些都是在挑戰(zhàn)硬盤讀寫速度,內(nèi)存讀寫速度以及CPU的運(yùn)算能力,假如1Tb的數(shù)據(jù)上面這三個要素不包含排序操作,讀取操作能在10毫秒內(nèi)完畢。或許海量數(shù)據(jù)的實(shí)時排序才有可能。可是眼下計(jì)算機(jī)是絕對沒有這個能力的。
那么現(xiàn)實(shí)場景下我們是怎樣解決海量數(shù)據(jù)的實(shí)時排序問題的呢?為了解決問題我們就必須有點(diǎn)逆向思維的意識了,另辟蹊徑的處理排序難題。第一種方式就是縮小須要排序的數(shù)據(jù)大小,那么數(shù)據(jù)庫的分區(qū)技術(shù)是一個非常好的手段,除了分區(qū)手段外,事實(shí)上另一個手段,前面我講到使用搜索技術(shù)能夠解決數(shù)據(jù)庫讀慢的難題,搜索庫本身能夠當(dāng)做一個讀庫,那么搜索技術(shù)是怎么來解決高速讀取海量數(shù)據(jù)的難題了,它的手段是使用索引,索引好比一本書的文件夾。我們想從書里檢索我們想要的信息,我們最有效率的方式就是先查詢文件夾。找到自己想要看的標(biāo)題,然后相應(yīng)頁碼,把書直接翻到那一頁,存儲系統(tǒng)索引的本質(zhì)和書的文件夾一樣。僅僅只是計(jì)算機(jī)領(lǐng)域的索引技術(shù)更加的復(fù)雜。事實(shí)上為數(shù)據(jù)建立索引,本身就是一個縮小數(shù)據(jù)范圍和大小的一種手段,這點(diǎn)它和分區(qū)是類似的。我們事實(shí)上能夠把索引當(dāng)做一張數(shù)據(jù)庫的映射表。一般存儲系統(tǒng)為了讓索引高效以及為了擴(kuò)展索引查找數(shù)據(jù)的準(zhǔn)確度,存儲系統(tǒng)在建立索引的時候還會跟索引建立好排序,那么當(dāng)用戶做實(shí)時查詢時候,他依據(jù)索引字段查找數(shù)據(jù),由于索引本身就有良好的排序,那么在查詢的過程里就能夠免去排序的操作,終于我們就能夠高效的獲取一個已經(jīng)排好序的結(jié)果集。
如今我們回到水平拆分海量數(shù)據(jù)排序的場景。前文里我提到了海量數(shù)據(jù)做分頁實(shí)時查詢能夠採用一種抽樣的方式進(jìn)行。盡管用戶的意圖是想進(jìn)行海量數(shù)據(jù)查詢。但是人不可能一下子消化掉所有海量數(shù)據(jù)的特點(diǎn)。因此我們能夠僅僅對海量數(shù)據(jù)的部分進(jìn)行操作。但是因?yàn)橛脩舻谋疽馐侨繑?shù)據(jù)。我們給出的抽樣數(shù)據(jù)怎樣能更加精確點(diǎn),那么就和我們在分布數(shù)據(jù)時候分布原則有關(guān)系,詳細(xì)落實(shí)的就是主鍵設(shè)計(jì)方案了。碰到這種場景就得要求我們的主鍵具有排序的特點(diǎn),那么我們就不得不探討下水平拆分里主鍵的排序問題了。
在前文里我提到一種使用固定哈希算法來設(shè)計(jì)主鍵的方案,當(dāng)時提到的限制條件就是主鍵本身沒有排序特性,僅僅有唯一性,因此哈希出來的值是唯一的,這種哈希方式事實(shí)上不能保證數(shù)據(jù)分布時候每臺server上落地?cái)?shù)據(jù)有一個先后的時間順序,它僅僅能保證在海量數(shù)據(jù)存儲分布式時候各個server近似均勻。因此這種主鍵設(shè)計(jì)方案碰到分頁查詢有排序要求時候事實(shí)上是起不到不論什么作用的。因此假設(shè)我們想讓主鍵有個先后順序最好使用遞增的數(shù)字來表示,可是遞增數(shù)字的設(shè)計(jì)方案假設(shè)依照我前面的起始數(shù)。步長方式就會有一個問題。那就是單庫單表的順序性能夠保障。跨庫跨表之間的順序是非常難保證的,這也說明我們對于水平拆分的主鍵字段對于邏輯表進(jìn)行全排序也是一件無法完畢的任務(wù)。
那么我們究竟該怎樣解決問題了。那么我們僅僅得使用單獨(dú)的主鍵生成server了,前文里我以前批評了主鍵生成server方案,文章發(fā)表后有個朋友找到我談?wù)摿讼逻@個問題,他說出了他們計(jì)劃的一個做法,他們自己研發(fā)了一個主鍵生成server,由于害怕這個server單點(diǎn)故障,他們把它做成了分布式,他們自己設(shè)計(jì)了一套簡單的UUID算法,使得這個算法適合集群的特點(diǎn)。他們打算用zookeeper保證這個集群的可靠性,好了。他們做法里最關(guān)鍵的一點(diǎn)來了,怎樣保證主鍵獲取的高效性。他說他們沒有讓每次生成主鍵的操作都是直接訪問集群,而是在集群和主鍵使用者之間做了個代理層,集群也不是頻繁生成主鍵的。而是每次生成一大批主鍵。這一大批主鍵值按隊(duì)列的方式緩存在代理層了,每次主鍵使用者獲取主鍵時候。隊(duì)列就消耗一個主鍵,當(dāng)然他們的系統(tǒng)還會檢查主鍵使用的比率,當(dāng)比率到達(dá)閥值時候集群就會收到通知。立即開始生成新的一批主鍵值。然后將這些值追加到代理層隊(duì)列里,為了保證主鍵生成的可靠性以及主鍵生成的連續(xù)性,這個主鍵隊(duì)列僅僅要收到一次主鍵請求操作就消費(fèi)掉這個主鍵,也不關(guān)心這個主鍵究竟是否真的被正常使用過,當(dāng)時我還提出了一個自己的疑問,要是代理掛掉了呢?那么集群該怎樣再生成主鍵值了,他說他們的系統(tǒng)沒有單點(diǎn)系統(tǒng)。就算是代理層也是分布式的,所以很可靠,就算所有server全掛了。那么這個時候主鍵生成server集群也不會再反復(fù)生成已經(jīng)生成過的主鍵值,當(dāng)然每次生成完主鍵值后,為了安全起見,主鍵生成服務(wù)會把生成的最大主鍵值持久化保存。
事實(shí)上這位朋友的主鍵設(shè)計(jì)方案事實(shí)上核心設(shè)計(jì)起點(diǎn)就是為了解決主鍵的排序問題,這也為實(shí)際使用單獨(dú)主鍵設(shè)計(jì)方案找到了一個非常現(xiàn)實(shí)的場景。假設(shè)能做到保證主鍵的順序性,同一時候數(shù)據(jù)落地時候依據(jù)這個順序依次進(jìn)行的,那么在單庫做排序查詢的準(zhǔn)確度就會非常高,查詢時候我們把查詢的條數(shù)均勻分布到各個server的表上,最后匯總的排序結(jié)果也是近似精確的。
自從和這位朋友聊到了主鍵生成服務(wù)的設(shè)計(jì)問題后以及我今天講到的一致性哈希的問題,我如今有點(diǎn)摒棄前文里說到的固定哈希算法的主鍵設(shè)計(jì)方案了,這個摒棄也是有條件限制的,主鍵生成服務(wù)的方案事實(shí)上是讓固定哈希方案更加完好,可是假設(shè)主鍵本身沒有排序性。僅僅有唯一性,那么這個做法對于排序查詢起不到什么作用,到了水平擴(kuò)展。固定哈希排序的擴(kuò)展會導(dǎo)致大量數(shù)據(jù)遷移。風(fēng)險和成本太高,而一致性哈希是固定哈希的進(jìn)化版,因此當(dāng)我們想使用哈希來分布數(shù)據(jù)時候,還不如一開始就使用一致性哈希,這樣就為興許的系統(tǒng)升級和維護(hù)帶來非常大的便利。
有網(wǎng)友在留言里還提到了哈希算法分布數(shù)據(jù)的一個問題,那就是硬件的性能對數(shù)據(jù)平均分配的影響,假設(shè)水平拆分所使用的server性能存在差異,那么平均分配是會造成熱點(diǎn)問題的出現(xiàn)。假設(shè)我們不去改變硬件的差異性,那么就不得不在分配原則上增加權(quán)重的算法來動態(tài)調(diào)整數(shù)據(jù)的分布,這樣就制造了人為的數(shù)據(jù)分布不均衡。那么到了上層的計(jì)算操作時候某些場景我們也會不自覺的增加權(quán)重的維度。可是作為筆者的我對這個做法是有異議的,這些異議詳細(xì)例如以下:
異議一:我個人覺得無論什么系統(tǒng)引入權(quán)重都是把問題復(fù)雜化的操作,權(quán)重往往都是權(quán)益之計(jì)。假設(shè)隨著時間推移還要進(jìn)一步擴(kuò)展權(quán)重算法,那么問題就變得越加復(fù)雜了。并且我個人覺得權(quán)重是非常難進(jìn)行合理處理的,權(quán)重假設(shè)還要演進(jìn)會變得異常復(fù)雜,這個復(fù)雜度可能會遠(yuǎn)遠(yuǎn)超出分布式系統(tǒng),數(shù)據(jù)拆分本身的難度。因此除非迫不得已我們還是盡量不去使用什么權(quán)重。就算有權(quán)重也不要輕易使用,看有沒有方式能夠消除權(quán)重的根本問題。
異議二:假設(shè)我們的系統(tǒng)后臺數(shù)據(jù)庫都是使用獨(dú)立server,那么一般都會讓最好的server服務(wù)于數(shù)據(jù)庫。這個做法本身就說明了數(shù)據(jù)庫的重要性,并且我們對數(shù)據(jù)庫的不論什么分庫分表的解決方式都會非常麻煩。非常繁瑣甚至非常危急,因此本篇開始提出了假設(shè)我們解決瓶頸問題前先考慮下硬件的問題,假設(shè)硬件能夠解決掉問題,優(yōu)先採取硬件方案。這就說明我們合理對待存儲問題的前提就是讓數(shù)據(jù)庫的硬件跟上時代的要求,那么假設(shè)有些硬件出現(xiàn)了性能瓶頸,是不是我們忽視了硬件的重要性了?
異議三:均勻分布數(shù)據(jù)不只能夠合理利用計(jì)算資源,它還會給業(yè)務(wù)操作帶來優(yōu)點(diǎn)。那么我們擴(kuò)展數(shù)據(jù)庫時候就讓各個server本身能力均衡,這個事實(shí)上不難的,假設(shè)老的server實(shí)在太老了,用新server替換掉,盡管會有全庫遷移的問題。但是這么粗粒度的數(shù)據(jù)平移。那但是比不論什么拆分方案的數(shù)據(jù)遷移難度低的多的。
好了。本篇就寫到這里,祝大家工作生活愉快!
轉(zhuǎn)載于:https://www.cnblogs.com/gccbuaa/p/7221336.html
總結(jié)
以上是生活随笔為你收集整理的关于大型站点技术演进的思考(七)--存储的瓶颈(7)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: swiper.js 多图片页面的懒加载l
- 下一篇: Linux 查看负载