原文:DESIGNING SCHEMALESS, UBER ENGINEERING’S SCALABLE DATASTORE USING MYSQL
譯文由杰微刊兼職譯者繆晨翻譯,杰微刊審校及發(fā)布
Schemaless的形成:根據Uber工程師的習慣使用MySQL設計的數據存儲,使我們可以 從2014 擴容到更高。這是Schemaless三部曲中的第一部。
在Mezzanine項目中我們描述了我們是如何將Uber的核心行程數據從單個的Postgres節(jié)點遷移到Schemaless,這是我們開發(fā)的一個容錯性很高、可用的數據存儲。本文將進一步講述它的架構、它在Uber基礎結構中的角色以及他是如何成為該角色的。
我們對新數據庫的迫切需求
2014年初,由于出行業(yè)務的迅猛增長,數據庫空間即將耗盡。每次入住新的城市以及行程的里程碑都會把我們推向危險的境地,直到我們發(fā)現到年末時Uber的基礎架構將無法繼續(xù)發(fā)揮效用:Postgre并不能存儲如此多的行程數據。我們的任務是實現Uber的下一代數據庫技術,一個耗時數月甚至幾乎整年的任務,大量的來自于我們世界各地研究所的工程師參與進來。
但是首先,在商業(yè)與開源選擇如此之多的當下,為什么要自己構建一個可擴展的數據庫。我們對我們新的行程數據存儲有5點關鍵的需求:
1、 我們新的解決方案需要可以通過增加服務器線性擴容,這是原有的Postgre所缺乏的。添加服務器應該能在增加硬盤存儲的同時減少系統(tǒng)的響應時間。
2、我們需要寫入的能力。我們之前通過Redis實現了一套簡單的緩沖機制,因此如果Postgre寫入失敗,我們可以稍后重試,因為行程已經在中間層存入了Redis當中。但是當行程數據在Redis當中時,是不能從Postgre中讀取的,然后一些功能就掛了,比如計費。很煩,不過至少我們沒有丟失行程數據。
隨著時間流逝,Uber逐漸成長,我們基于Redis的解決方案不能擴容。Schemaless需要支持一種類似Redis的機制,但最好還是寫完即時可讀。
3、我們需要一種機制通知下游依賴。在現有系統(tǒng)中,我們同時處理多個行程組件(比如計費,分析等)。這種處理方式很容易出錯:如果任何一步失敗了,我們就比如從頭重試,即使一些組件處理已經成功了。這就不能擴容了,因此我們想把這些步驟打碎成獨立的步驟,由數據變更發(fā)起。我們曾經確實有一個異步事件系統(tǒng),但是它是基于 Kafka 0.7的。我們沒法讓它無損運行,因此我們希望新系統(tǒng)有一些類似的機制,但是可以無損運行。
4、 我們需要副索引。由于我們是從Postgre遷移的,那新的存儲系統(tǒng)需要支持Postgre的索引,會按照習慣用副索引搜索行程數據。
5、我們需要運維夠信賴的可靠系統(tǒng),因為其中包含了行程數據的關鍵任務。如果凌晨3點我們接到叫車請求,但是這時數據存儲無法響應查詢,導致業(yè)務宕機,我們是否有相關操作知識可以快速解決這個問題。
鑒于以上種種,我們分析了幾種常用的選擇的優(yōu)勢和潛在的限制,比如Cassandra、Riak、MongoDB等。出于說明的目的,我們提供了如下圖表,展示了不同系統(tǒng)選擇下的不同功能組合:
所有的三個系統(tǒng)都可以通過在線增加節(jié)點線性擴容,只有一對系統(tǒng)可以在宕機時收到寫操作。所有的解決方案中都沒有內置的方式將變化通知下游依賴,因此可能需要在應用層實現該功能。它們都索引功能,但是如果你想索引多個不同的值,查詢會變慢,因為他們使用分散查詢并聚合結果的方式查詢了所有節(jié)點。最后對于其中的一些系統(tǒng)有過單集群的使用經驗,但不提供面向用戶的在線流量,而且在我們的服務連接的時候有各種各樣的運維問題。
最終我們的確定運維信賴為主要因素,因為它包含了行程數據的關鍵任務。 可供選擇的解決方案理論上可能都是可靠的,但是我們是否有運維的知識來立即發(fā)揮其最大功效,基于此我們決定基于Uber的使用情況開發(fā)自己的解決方案。這不僅基于我們使用的技術,而且根據成員的經驗。
需要注意的是我們對這些系統(tǒng)的研究持續(xù)了兩年,沒有發(fā)現適合行程數據存儲的,但是我們已經在其它領域成功接受了Cassandra與Riak作為我們的基礎服務,而且在生產環(huán)境使用這些為數百萬級的用戶提供服務。
在Schemaless中我們相信
由于以上的所有選擇在規(guī)定的時間內都不能完全滿足自己的需求,我們決定構建我們自己的系統(tǒng)使運維盡量簡單,也參考了其它廠擴容的經驗。這個設計的靈感來自于Friendfeed,運維的方面則參考了Pinterest。