編者按:高可用架構(gòu)分享及傳播在架構(gòu)領(lǐng)域具有典型意義的文章,本文由肖鵬在高可用架構(gòu)群分享。轉(zhuǎn)載請(qǐng)注明來(lái)自高可用架構(gòu)公眾號(hào)「 ArchNotes 」。
數(shù)據(jù)庫(kù)專家的成長(zhǎng)感觸“與 MySQL 結(jié)緣主要也是源于興趣。第一份工作是在一家小公司,由于人手有限,各個(gè)領(lǐng)域的工作都要接觸,相比之下我發(fā)現(xiàn)還是對(duì)數(shù)據(jù)庫(kù)最感興趣,所以就一直從事和數(shù)據(jù)庫(kù)相關(guān)的技術(shù)工作了。而隨著工作年限的增加,在數(shù)據(jù)庫(kù)方面積累的經(jīng)驗(yàn)也逐漸增多,越來(lái)越覺(jué)得數(shù)據(jù)庫(kù)管理員(DBA)是一個(gè)偏實(shí)踐的工種,很多理論上的東西在現(xiàn)實(shí)中會(huì)有各種的變化,比如“反范式”設(shè)計(jì)等。因此,如果想成為數(shù)據(jù)庫(kù)方面的專家,建議大家一定要挑選好環(huán)境,大平臺(tái)很多時(shí)候會(huì)由于量變引發(fā)質(zhì)變產(chǎn)生很多有挑戰(zhàn)的問(wèn)題,而解決這些問(wèn)題是成為技術(shù)專家的必經(jīng)之路?!? —— 肖鵬 微博數(shù)據(jù)庫(kù)經(jīng)歷的變遷首先為大家分享微博數(shù)據(jù)庫(kù)經(jīng)歷的幾個(gè)重要的階段。? 初創(chuàng)階段 初期微博作為一個(gè)內(nèi)部創(chuàng)新產(chǎn)品,功能比較簡(jiǎn)潔,數(shù)據(jù)庫(kù)架構(gòu)采用的是標(biāo)準(zhǔn) 1M/2S/1MB 結(jié)構(gòu),按照讀寫(xiě)分離設(shè)計(jì),主庫(kù)承擔(dān)寫(xiě)入,而從庫(kù)承擔(dān)訪問(wèn)。如果訪問(wèn)壓力過(guò)大,可以通過(guò)擴(kuò)容從庫(kù)的數(shù)量獲得 scale out 的能力。 上圖紅色代表寫(xiě)入、綠色代表讀取、黑色映射到內(nèi)部結(jié)構(gòu),由圖可知,業(yè)務(wù)僅僅進(jìn)行了垂直拆分,也就是按照業(yè)務(wù)模塊比如用戶、內(nèi)容、關(guān)系等進(jìn)行區(qū)分,并單獨(dú)使用了數(shù)據(jù)庫(kù)。在初期這其實(shí)是非常好的架構(gòu),在功能模塊上提供了解耦的基礎(chǔ),出現(xiàn)問(wèn)題也可以很方便地進(jìn)行定位、在最開(kāi)始就可以做到按照不同的功能模塊進(jìn)行降級(jí)。
個(gè)人認(rèn)為,在初期,這種架構(gòu)其實(shí)就可以滿足業(yè)務(wù)的增長(zhǎng)了,沒(méi)有必要進(jìn)行過(guò)度設(shè)計(jì),開(kāi)始就搞得過(guò)于復(fù)雜可能會(huì)導(dǎo)致喪失敏捷的可能。
爆發(fā)階段 隨著微博上線之后用戶活躍度的增高,數(shù)據(jù)庫(kù)的壓力也與日俱增,我們首先通過(guò)采購(gòu)高性能的硬件設(shè)備來(lái)對(duì)單機(jī)性能進(jìn)行 scale up,以達(dá)到支撐業(yè)務(wù)高速發(fā)展的需求。然后,通過(guò)使用高性能設(shè)備爭(zhēng)取來(lái)的時(shí)間對(duì)微博進(jìn)行整體上的業(yè)務(wù)垂直拆分,將用戶、關(guān)系、博文、轉(zhuǎn)發(fā)、評(píng)論等功能模塊分別獨(dú)立存儲(chǔ),并在垂直拆分的基礎(chǔ)上,對(duì)于一些預(yù)期會(huì)產(chǎn)生海量數(shù)據(jù)的業(yè)務(wù)模塊再次進(jìn)行了二次拆分。
對(duì)于使用硬件這里多說(shuō)幾句,由于微博最開(kāi)始的時(shí)候就出現(xiàn)了一個(gè)很高的用戶增長(zhǎng)峰值,在這個(gè)階段我們?cè)诩夹g(shù)上的積累不是很豐富,而且最主要的是沒(méi)有時(shí)間進(jìn)行架構(gòu)改造,所以通過(guò)購(gòu)買(mǎi) PCIE-Flash 設(shè)備來(lái)支持的很多核心業(yè)務(wù),我現(xiàn)在還清楚記得最開(kāi)始的 feed 系統(tǒng)是重度依賴 MySQL 的,在 2012 年的春晚當(dāng)天 MySQL 寫(xiě)入 QPS 曾經(jīng)飆到過(guò) 35000,至今記憶猶新。
雖然看上去高性能硬件的價(jià)格會(huì)比普通硬件高很多,但是爭(zhēng)取來(lái)的時(shí)間是最寶貴的,很有可能在產(chǎn)品生命的初期由于一些性能上的問(wèn)題引發(fā)產(chǎn)品故障,直接導(dǎo)致用戶流失,更加得不償失。所以,個(gè)人認(rèn)為在前期的爆發(fā)階段,暴力投入資金解決問(wèn)題其實(shí)反而是最劃算的。
繼續(xù)說(shuō)數(shù)據(jù)庫(kù)拆分,以博文為例。博文是微博用戶主要產(chǎn)生的內(nèi)容,可預(yù)見(jiàn)會(huì)隨著時(shí)間維度不斷增大,最終會(huì)變得非常巨大,如何在滿足業(yè)務(wù)性能需求的情況下,盡可能地使用較少的成本存儲(chǔ),這是我們面臨的一個(gè)比較有挑戰(zhàn)性的問(wèn)題。
上圖乍一看和上一張圖一樣,但這其實(shí)只是一個(gè)博文功能模塊的數(shù)據(jù)庫(kù)架構(gòu)圖,我們可以看到索引和內(nèi)容各自分了很多的端口,每個(gè)端口中又分了很多的 DB,每個(gè) DB 下的表先 hash 后按照時(shí)間維度進(jìn)行了拆分,這樣就可以讓我們?cè)诤笃谟龅饺萘科款i或者性能瓶頸的時(shí)候,可以選擇做歸檔或者調(diào)整部署結(jié)構(gòu),無(wú)論選擇那種都非常的方便。另外,在做歸檔之后,還可以選擇使用不同的硬件來(lái)承擔(dān)不同業(yè)務(wù),提高硬件的利用率、降低成本。
在這個(gè)階段,我們對(duì)很多的微博功能進(jìn)行了拆分改造,比如用戶、關(guān)系、博文、轉(zhuǎn)發(fā)、評(píng)論、贊等,基本上將核心的功能都進(jìn)行了數(shù)據(jù)拆分,以保障在遇到瓶頸的時(shí)候可以按照預(yù)案進(jìn)行改造和調(diào)整。
沉淀階段 在上一個(gè)階段,微博的數(shù)據(jù)庫(kù)經(jīng)歷了很多的拆分改造,這也就直接造成了規(guī)模成倍增長(zhǎng)的狀況,而業(yè)務(wù)經(jīng)歷了高速增長(zhǎng)之后,也開(kāi)始趨于穩(wěn)定。在這個(gè)階段,我們開(kāi)始著重進(jìn)行自動(dòng)化的建設(shè),將之前在快速擴(kuò)張期間積攢下來(lái)的經(jīng)驗(yàn)用自動(dòng)化工具加以實(shí)現(xiàn),對(duì)外形成標(biāo)準(zhǔn)化和流程化的平臺(tái)服務(wù)。我們相繼建設(shè)改造了備份系統(tǒng)、監(jiān)控系統(tǒng)、AutoDDL 系統(tǒng)、MHA 系統(tǒng)、巡檢系統(tǒng)、慢查系統(tǒng)、maya 中間件系統(tǒng)。并且為了提高業(yè)務(wù)使用效率、降低溝通成倍,相對(duì)于內(nèi)部管理系統(tǒng),重新開(kāi)發(fā)了 iDB 系統(tǒng)供數(shù)據(jù)庫(kù)平臺(tái)的用戶使用。通過(guò) iDB 系統(tǒng),用戶可以很便捷地了解自己業(yè)務(wù)數(shù)據(jù)庫(kù)的運(yùn)行狀態(tài),并可以直接提交對(duì)數(shù)據(jù)庫(kù)的 DDL 修改需求,DBA 僅需點(diǎn)擊審核通過(guò),即可交由 Robot 在線上執(zhí)行,不但提高了工作效率,也提高了安全性和規(guī)范性。
由于涉及的自動(dòng)化系統(tǒng)比較多,就不一一展開(kāi)描述了,其實(shí)個(gè)人理解,在產(chǎn)品發(fā)展到一定階段之后無(wú)論如何運(yùn)維都會(huì)進(jìn)入到自動(dòng)化階段,因?yàn)榍捌诨顑荷伲斯ぷ銐蛑С肿兏推渲胁僮?,且有很多特殊情況需要人,尤其是人腦的介入判斷和處理。
這里要額外重點(diǎn)說(shuō)一下規(guī)范的重要性。以 MySQL 開(kāi)發(fā)規(guī)范來(lái)說(shuō),如果提前做好約定,并進(jìn)行好限制,雖然開(kāi)發(fā)人員在使用的過(guò)程中會(huì)感覺(jué)受到的約束,但是這可以避免線上發(fā)生完全不可控的故障,并且有些問(wèn)題由于規(guī)范的存在就永遠(yuǎn)不會(huì)發(fā)生了。
舉個(gè)例子。MySQL 的慢查是導(dǎo)致線上性能慢的罪魁禍?zhǔn)?,但是很多時(shí)候并不是沒(méi)有 index,只是由于代碼寫(xiě)得有問(wèn)題,引起了隱式轉(zhuǎn)換等問(wèn)題。在這種情況下,我們一般建議所有的 where 條件都加上雙引號(hào),這樣就可以直接消除隱式轉(zhuǎn)換的可能性了,開(kāi)發(fā)人員在寫(xiě)代碼的時(shí)候也不用刻意去考慮到底是字符型還是 int 型。
繼續(xù)說(shuō)自動(dòng)化。過(guò)了初期階段、規(guī)模擴(kuò)大之后,就會(huì)出現(xiàn)活多人少的情況,這種壓力會(huì)促使大家自動(dòng)去尋求解決方案,也就自然而然地進(jìn)行了自動(dòng)化改造了。當(dāng)然,業(yè)務(wù)穩(wěn)定后有時(shí)間開(kāi)發(fā)了,其實(shí)是一個(gè)更重要的原因。
個(gè)人認(rèn)為自動(dòng)化分為兩個(gè)階段。第一個(gè)階段是機(jī)器替代人工,也就是將大部分機(jī)械勞動(dòng)交給程序來(lái)實(shí)現(xiàn),解決的是批量操作,重復(fù)性勞動(dòng)的問(wèn)題;第二個(gè)階段是機(jī)器替人,也就是機(jī)器可以替人進(jìn)行一定的判斷之后進(jìn)行自我選擇,解放的是人力。不過(guò)第二個(gè)階段是我們一直追求的理想狀態(tài),至今也僅完成了很簡(jiǎn)單的一些小功能,比如動(dòng)態(tài)調(diào)整 max mem 等邏輯非常簡(jiǎn)單的功能。
微博數(shù)據(jù)庫(kù)的優(yōu)化和設(shè)計(jì)接下來(lái)介紹一下微博數(shù)據(jù)庫(kù)平臺(tái)最近做的一些改進(jìn)和優(yōu)化。
數(shù)據(jù)庫(kù)平臺(tái)并不僅有 MySQL 還有 Redis、Memcached、HBase 等數(shù)據(jù)庫(kù)服務(wù),而在緩存為王的趨勢(shì)下,微博 2015 年重點(diǎn)將研發(fā)精力投入在 Redis 上。
微博使用 Redis 的時(shí)間較早,并且一開(kāi)始量就很大,于是在實(shí)際使用過(guò)程中遇到了很多實(shí)際的問(wèn)題,我們的內(nèi)部分支版本都是針對(duì)這些實(shí)際問(wèn)題進(jìn)行優(yōu)化的,比較有特點(diǎn)的有如下幾個(gè)。
Redis 中間件 在 2015 年我們自研的 Redis 中間件 tribe 系統(tǒng)完成了開(kāi)發(fā)和上線,tribe 采用有中心節(jié)點(diǎn)的 proxy 架構(gòu)設(shè)計(jì),通過(guò) configer server 管理集群節(jié)點(diǎn),并借鑒官方 Redis cluster 的 slot 分片的設(shè)計(jì)思路來(lái)完成數(shù)據(jù)存儲(chǔ),最終實(shí)現(xiàn)了路由、分片、自動(dòng)遷移、fail over 等功能,并且預(yù)留了操作和監(jiān)控的 API 接口,以便同其他的自動(dòng)化運(yùn)維系統(tǒng)對(duì)接。 我們開(kāi)發(fā) tribe 最主要的目的是解決自動(dòng)遷移的問(wèn)題,由于 Redis 內(nèi)存使用會(huì)呈現(xiàn)波動(dòng)性變化,很多時(shí)候前一天還是 10%,第二天有可能就變成了 80%,這種時(shí)候人工去遷移肯定無(wú)法響應(yīng)業(yè)務(wù)的變化,而且如果這時(shí)候恰巧還碰到了物理內(nèi)存上的瓶頸,那就更麻煩了,涉及業(yè)務(wù)進(jìn)行重構(gòu)數(shù)據(jù) hash 都有可能導(dǎo)致故障的發(fā)生。
基于 slot 的動(dòng)態(tài)遷移,首先對(duì)業(yè)務(wù)無(wú)感知,其次不再需要整臺(tái)服務(wù)器,只需找有可用內(nèi)存的服務(wù)器就可以將部分 slot 遷移過(guò)去,直接解決擴(kuò)容遷移問(wèn)題,可以極大地提高服務(wù)器的利用率、降低成本。
提供的路由功能,可以降低開(kāi)發(fā)門(mén)檻,再也不用將資源邏輯配置寫(xiě)到代碼或者前端配置文件中了,每次更改變更的時(shí)候也不用再進(jìn)行上線了,這極大地提高了開(kāi)發(fā)效率,也降低了線上變更引發(fā)的故障風(fēng)險(xiǎn),畢竟 90% 的故障是主動(dòng)變更引發(fā)的。
補(bǔ)充一點(diǎn),關(guān)于重復(fù)造輪子,個(gè)人認(rèn)為每個(gè)公司都有自己的場(chǎng)景,開(kāi)源軟件可以給我們提供一個(gè)很好的解決思路,但并不能百分百適應(yīng)應(yīng)用場(chǎng)景,所以重構(gòu)并不是堅(jiān)決不可接受的,有些事情你總要妥協(xié)。
Databus 由于我們先有 MySQL 后有 Redis 和 HBase 等數(shù)據(jù)庫(kù),故存在一種場(chǎng)景就是目前數(shù)據(jù)已經(jīng)寫(xiě)入 MySQL 中,但是需要將這些數(shù)據(jù)同步到其他的數(shù)據(jù)庫(kù)中,我們?yōu)榇碎_(kāi)發(fā)了 Databus,可以基于 MySQL 的 binlog 將數(shù)據(jù)同步到其他異構(gòu)的數(shù)據(jù)庫(kù)中,并且支持自定義業(yè)務(wù)邏輯。目前已經(jīng)實(shí)現(xiàn)了 MySQL 到 Redis 和 MySQL 到 HBase 的數(shù)據(jù)流向,下一步計(jì)劃開(kāi)發(fā) Redis 到 MySQL 的數(shù)據(jù)流向。 我們開(kāi)發(fā) databus 最初的初衷是解決寫(xiě) Redis 的問(wèn)題,由于有些數(shù)據(jù)即需要寫(xiě)入 MySQL 中,也需要寫(xiě)入 Redis 中。如果在前端開(kāi)啟雙寫(xiě)也是可以解決的,但是這會(huì)造成代碼復(fù)雜現(xiàn)象;如果在后端實(shí)現(xiàn)一個(gè)數(shù)據(jù)鏈路,會(huì)讓代碼更加清晰,同時(shí)也可以保障數(shù)據(jù)的最終一致性。后來(lái)在實(shí)際應(yīng)用中,databus 慢慢也開(kāi)始承擔(dān)導(dǎo)數(shù)據(jù)的功能。
下面說(shuō)一下目前微博積累下來(lái)的數(shù)據(jù)庫(kù)的設(shè)計(jì)習(xí)慣。通常來(lái)說(shuō)我們都會(huì)采用一些“反范式”的設(shè)計(jì)思路,而“反范式“設(shè)計(jì)帶來(lái)便利的同時(shí)確實(shí)也帶來(lái)了一些問(wèn)題,尤其是在數(shù)據(jù)規(guī)模變大之后。有如下幾種解決方案。
另外一點(diǎn)就是,如果數(shù)據(jù)庫(kù)預(yù)估量比較大的話,我們會(huì)參考博文的設(shè)計(jì)思路,在最開(kāi)始的時(shí)候進(jìn)行索引和內(nèi)容的分離,并設(shè)計(jì)好 hash 和時(shí)間維度的分表,最大可能地減少后續(xù)拆分時(shí)可能遇到的問(wèn)題和困難。
微博數(shù)據(jù)庫(kù)平臺(tái)未來(lái)的計(jì)劃最后,我想分享一下微博數(shù)據(jù)庫(kù)平臺(tái)發(fā)展的一點(diǎn)思考,希望可以給大家提供一些思路,當(dāng)然,更希望大家也給我提出一些建議和意見(jiàn),讓我少走彎路、少掉坑。
隨著業(yè)務(wù)的發(fā)展,會(huì)遇到越來(lái)越多的場(chǎng)景,我們希望可以引進(jìn)最適合的數(shù)據(jù)庫(kù)來(lái)解決場(chǎng)景問(wèn)題,比如 PostgreSQL、SSDB 等。同時(shí),利用 MySQL 新版本的特性,比如 MySQL 5.7 的并行復(fù)制、GTID、動(dòng)態(tài)調(diào)整 BP,不斷優(yōu)化現(xiàn)有服務(wù)的性能和穩(wěn)定性。
另外,推進(jìn)現(xiàn)有 NoSQL 服務(wù)的服務(wù)化,通過(guò)使用 proxy 將存儲(chǔ)節(jié)點(diǎn)進(jìn)行組織之后對(duì)外提供服務(wù),對(duì)外降低開(kāi)發(fā)人員的開(kāi)發(fā)復(fù)雜度和獲取資源的細(xì)度,對(duì)內(nèi)提高單機(jī)利用率并解決資源層橫向擴(kuò)展的瓶頸問(wèn)題。
同時(shí),嘗試?yán)酶鞔笤朴?jì)算資源,實(shí)現(xiàn) cache 層的動(dòng)態(tài)擴(kuò)縮容,充分利用云計(jì)算的彈性資源,解決業(yè)務(wù)訪問(wèn)波動(dòng)的問(wèn)題。 Q & A1. 數(shù)據(jù)和索引分離是業(yè)務(wù)層做還是中間件做?感覺(jué)中間件做了很多工作,這部分能不能稍微展開(kāi)一下? 由于在當(dāng)初拆分改造的時(shí)候并沒(méi)有考慮中間件的方案,故目前是業(yè)務(wù)邏輯上實(shí)現(xiàn)的索引和內(nèi)容的分離。以我個(gè)人的經(jīng)驗(yàn)來(lái)看,即使使用中間件的解決方案,依然應(yīng)該在業(yè)務(wù)邏輯層將索引和內(nèi)容分割。 中間件最核心的功能就是讓程序和后端資源隔離,后端不管有多少資源,對(duì)于程序來(lái)說(shuō)都是一個(gè)統(tǒng)一的入口,所以中間件解決的是水平拆分的問(wèn)題,而索引和內(nèi)容分離屬于垂直拆分的范圍,個(gè)人認(rèn)為不應(yīng)該由中間件解決。
2. 印象最深的一次數(shù)據(jù)庫(kù)服務(wù)故障能否回憶并說(shuō)幾點(diǎn)注意事項(xiàng)? 要說(shuō)印象最深的一次就是數(shù)據(jù)庫(kù)服務(wù)的故障,當(dāng)時(shí)有個(gè)同事不小心執(zhí)行了 drop table 命令,了解數(shù)據(jù)庫(kù)的人都知道這個(gè)命令有多大的威力,我們利用架構(gòu)上面爭(zhēng)取來(lái)的時(shí)候緊急進(jìn)行了單表恢復(fù),雖然降級(jí)了一段時(shí)間,但是整體上并沒(méi)有影響用戶。 對(duì)此我要說(shuō)的注意事項(xiàng)就是規(guī)范。自那之后,我們修改了所有刪表需求的流程,并保證嚴(yán)格執(zhí)行,無(wú)論多么緊急的刪除需求都必須進(jìn)行24小時(shí)的冷卻,具體如下。
3. 在微博暴漲階段,對(duì)表進(jìn)行拆分的部分,“對(duì)索引和內(nèi)容進(jìn)行hash,之后再按著時(shí)間緯度進(jìn)行拆分”,這個(gè)做hash的部分是否能展開(kāi)說(shuō)一下? 這個(gè)其實(shí)沒(méi)有那么復(fù)雜。首先我們會(huì)預(yù)估一下一年大概的數(shù)量級(jí)別,然后計(jì)算需要拆分的表數(shù)目,并且盡量將每個(gè)表控制在 3 千萬(wàn)行記錄以內(nèi)(當(dāng)然這只是希望,現(xiàn)實(shí)證明計(jì)劃趕不上變化)。比如我們使用模 1024 的辦法,根據(jù)博文 id 將所有產(chǎn)生的博文分到 1024 張表中(這個(gè)博文 id 又涉及我們的 uuid 全局發(fā)號(hào)器就不展開(kāi)了)。 由于微博大部分用戶產(chǎn)生的內(nèi)容都會(huì)和時(shí)間掛鉤,所以時(shí)間維度對(duì)我們來(lái)說(shuō)是強(qiáng)屬性,基本都會(huì)有,假設(shè)每個(gè)月都建表,這樣就等于每個(gè)月會(huì)生產(chǎn) 1024 張表。如果數(shù)據(jù)庫(kù)的容量出現(xiàn)瓶頸了,我們就可以根據(jù)時(shí)間維度來(lái)解決,比如將 2010 年的所有表都遷移到其他的數(shù)據(jù)庫(kù)中。 4. Linkedin 多年前出過(guò)一個(gè)類似 databus 的項(xiàng)目,后續(xù)也有一些開(kāi)源項(xiàng)目支持 MySQL 到 HBase、ES 等的數(shù)據(jù)同步,微博的做法能不能展開(kāi)一下? 這個(gè)異構(gòu)數(shù)據(jù)的同步確實(shí)很多公司都有,據(jù)我所知阿里的 DRC 也是做同樣的事情。我們的實(shí)現(xiàn)思路主要就是依賴于 MySQL 的 binlog,大家都知道在 MySQL 的 binlog 設(shè)置成 row 格式的情況下,它會(huì)將所有受到影響的數(shù)據(jù)都記錄到日志中,這樣就提供了所有數(shù)據(jù)的變化。 我們通過(guò)解析 row 格式的 MySQL binglog 將數(shù)據(jù)的變化讀取到 databus 中,然后將實(shí)際需要的業(yè)務(wù)邏輯通過(guò)。so 文件 load 到 databus 中,databus 會(huì)根據(jù)業(yè)務(wù)邏輯重新再處理一下數(shù)據(jù)的變化,然后輸出給下游資源。 databus 這個(gè)項(xiàng)目我們已經(jīng)開(kāi)源,大家可以直接在 GitHub 上搜“MyBus”即可。 5. 問(wèn)題 1 中說(shuō)的索引是指什么,如何找到對(duì)應(yīng)內(nèi)容的算法? 索引其實(shí)指的并不是內(nèi)容的算法,舉個(gè)例子,如果你需要存儲(chǔ)博文,那么必然會(huì)存儲(chǔ)一個(gè)唯一的 id 來(lái)進(jìn)行區(qū)分,然后會(huì)存儲(chǔ)一些這個(gè)博文發(fā)表時(shí)候的狀態(tài),比如誰(shuí)發(fā)的、什么時(shí)候發(fā)的、我們認(rèn)為這些狀態(tài)和 id 都是索引;而博文內(nèi)容就是實(shí)際的內(nèi)容,由于內(nèi)容比較大,和索引存儲(chǔ)在一起會(huì)導(dǎo)致 MySQL 的性能下降,而且很多查詢只需要最終拿到博文 id 其實(shí)就等于拿到了實(shí)際的博文。 我們可以對(duì)索引進(jìn)行各種過(guò)濾之后得到一個(gè)最終要輸出給用戶的索引 list,再根據(jù)這個(gè) list 從內(nèi)容庫(kù)中查找實(shí)際內(nèi)容,這樣就符合 MySQL 的返回結(jié)果集越小性能越高的規(guī)律,從而起到優(yōu)化的效果。 6. NoSQL發(fā)揮著哪些作用? 在微博NoSQL發(fā)揮了越來(lái)越重要的作用,比如說(shuō) rediscounter,我們自研的計(jì)數(shù)服務(wù),當(dāng)初計(jì)數(shù)存貯在 MySQL 中,由于所有計(jì)數(shù)都是 update set count = count +1 這種高并發(fā)對(duì)單行數(shù)據(jù)的寫(xiě)操作,會(huì)引發(fā)MySQL多種鎖,而且并發(fā)越高鎖得越厲害。 由下圖可見(jiàn),如果對(duì)單行的并發(fā)操作達(dá)到500 以上,tps就會(huì)從上萬(wàn)變成幾百,所以MySQL無(wú)論怎么優(yōu)化都無(wú)法很好地支持這個(gè)業(yè)務(wù)場(chǎng)景,而Redis就可以。 我個(gè)人認(rèn)為,NoSQL 就像瑞士軍刀,在最適合的地方它就是最優(yōu)的方案,個(gè)人認(rèn)為這也是 NoSQL 未來(lái)發(fā)展的方向,每一個(gè)都有一個(gè)最佳場(chǎng)景。 7. 我們公司將來(lái)會(huì)有很多智能設(shè)備,今年或許就兩萬(wàn)個(gè)以上的設(shè)備,一年后可能再翻很多倍,要收集數(shù)據(jù),都是 JSON 報(bào)文格式,JSON 里字段標(biāo)識(shí)不同類型的報(bào)文,看似不太適合以字符串存進(jìn) varchar 或 longtext 字段,DB 存儲(chǔ)是否可充分利用 MYSQL 5.7 的原生JSON,存一列就搞定,而不必用無(wú)法擴(kuò)展的“寬列”進(jìn)行存儲(chǔ),或者POSTGRES 還是其他的 DB 能提供更方便的存儲(chǔ)嗎?前期還用的時(shí)候,MySQL 5.7 還沒(méi) FINAL, 利用 mariadb 多主分擔(dān)N多設(shè)備接進(jìn)來(lái),DB 寫(xiě)入層的負(fù)載,對(duì)這種大量設(shè)備一直要傳數(shù)據(jù)的寫(xiě)入場(chǎng)景有什么指導(dǎo)? 我們其實(shí)也在看 MySQL 5.7 的新特性,其中 JSON 對(duì)于數(shù)據(jù)庫(kù)設(shè)計(jì)會(huì)帶來(lái)比較大的沖擊,按照你的說(shuō)法,確實(shí)不應(yīng)該使用 varchar 或者 text 之類的字段,不過(guò)我個(gè)人建議智能設(shè)備這種場(chǎng)景,如果有可能,最好直接上 HBase,因?yàn)檫t早數(shù)據(jù)量會(huì)變得 MySQL 難以支撐,這屬于天生沒(méi)有優(yōu)勢(shì)。 8. “數(shù)據(jù)和索引分離”是什么意思呢,是數(shù)據(jù)文件和索引文件分開(kāi)存放到不同機(jī)器上嗎? 應(yīng)該是內(nèi)容和索引,這樣更好理解,大家把這個(gè)理解為業(yè)務(wù)層上的垂直拆分就好。由于進(jìn)行了垂直拆分,必然存在于不同的數(shù)據(jù)庫(kù)實(shí)例中,所以可以放在一臺(tái)物理機(jī)上,也可以放到不同的物理機(jī)上,我們按照習(xí)慣都是放在不同的物理機(jī)上的,以避免互相干擾。
9. 哪些信息存MySQL?哪些存NoSQL?用的是哪種NoSQL? 這就涉及一個(gè)分層存儲(chǔ)的問(wèn)題了,目前我們主流是 MySQL + Redis+mc,mc 和 Redis 都用來(lái)抗熱點(diǎn)和峰值,而 MySQL 則為數(shù)據(jù)落地,保障最終有原始數(shù)據(jù)可查。大部分請(qǐng)求會(huì)到 mc 或者 Redis 層就返回了,只有不到 1% 的數(shù)據(jù)會(huì)到 MySQL上。 當(dāng)然也有特殊的,比如之前說(shuō)的計(jì)數(shù)服務(wù),我們就把 rediscounter 當(dāng)初落地存儲(chǔ)使用,后面并沒(méi)有在 MySQL 中再存儲(chǔ)一份數(shù)據(jù)了。 最后,個(gè)人認(rèn)為 NoSQL 最大的優(yōu)勢(shì)是開(kāi)發(fā)的便捷性,開(kāi)發(fā)人員使用 NoSQL 會(huì)比使用 MySQL 更簡(jiǎn)單,因?yàn)榫褪?KV 結(jié)構(gòu),所有查詢都是主鍵查詢,不用考慮 index 優(yōu)化的問(wèn)題,也不用考慮如何建表,這對(duì)于現(xiàn)在的互聯(lián)網(wǎng)速度來(lái)說(shuō)是有致命誘惑的。 10. 請(qǐng)問(wèn)全局唯一發(fā)號(hào)器和自動(dòng)生成id對(duì)業(yè)務(wù)來(lái)說(shuō)優(yōu)劣分別是什么? 全局唯一發(fā)號(hào)器有很多實(shí)現(xiàn)的方案,我們是用 mc 協(xié)議改的 Redis,主要追求性能。我也見(jiàn)過(guò)使用 MySQL 的自增 id 作為發(fā)號(hào)器,但是由于 MySQL 的鎖太重,業(yè)務(wù)起量之后經(jīng)常會(huì)出現(xiàn)問(wèn)題,所以就放棄了。 再說(shuō)另外一個(gè)好處,全局唯一發(fā)號(hào)器的開(kāi)發(fā)難度并不高,可以將一些你想要的屬性封裝到 uuid 中,比如 id 的格式可以是這樣“時(shí)間戳 + 業(yè)務(wù)flog + 自增序列數(shù)”,這樣你拿到這個(gè) id 的時(shí)候直接就可以知道時(shí)間和對(duì)應(yīng)的業(yè)務(wù)了,與 MySQL 自身發(fā)出來(lái)的簡(jiǎn)單的一個(gè)沒(méi)意義的序列號(hào)相比,可以做更多的事情。 |
|
來(lái)自: 昵稱31044368 > 《技術(shù)》