電商不僅僅是大數據驅動的,京東用大數據為用戶、商品等帶來運營效率的提升。同時,從在線的數據訪問來講,電商業務需要非常快速的數據訪問。大家可以看到,京東隨便打開京東首頁或類似的電商首頁,圖片是京東的資產,是商品形象的描述,可以用CDN加速。除了圖片之外,其他幾乎都是動態內容,量很大,且是頻繁被改寫的,它們需要非常快速的訪問,比如說商品的詳情、價格、品類下推薦的結果等許多內容,打開個商品詳情頁面或列表頁,后臺邏輯是很復雜的,需要非常多的數據去展現。
這個過程中,一個是快速的數據訪問對終端用戶的體驗有非常關鍵的影響。另外,從京東產品工程師開發的產品角度出發,另一個訴求就是關注業務邏輯,而不應該花時間優化后臺在線存儲的性能。Jim Gray是數據庫領域的泰斗級人物,他其中一句話我記得很清楚,即“Memory is the new disk(內存是新的磁盤)”。07、08年時京東買的內存大小標準配置是4G左右,很快4G、8G、16G一路下來,很多公司都會采購158、265G內存,估計明年都會用1T內存。京東都用265G內存加萬兆網卡來做,單機內存在快速變大,整體很多在線的小結構和半結構化數據存放在內存里,這個問題是不大的,也是非常合理的。而且用內存做在線存儲確實有弊端,就是成本在一個時間段內有些偏高,但是除此之外卻帶來很多性能、管理等各方面的便捷性,兩相權衡下,在一定程度上,成本的升高對有一定規模和業務比較重要的公司可以接受,而且京東可以用技術手段降低這個成本。
JIMDB的全稱為The Jingdong In-Memory Database,這個系統的名字是大概2014年初起的,它并不是嚴格的關系型數據庫,而是一種新型的,以內存為中心的全部托管、全管理服務化的數據庫。它是以內存為中心的數據存儲,主要針對在線的結構或半結構化的數據,過去兩年一直在持續建設。從目前的業務價值角度,它支撐了京東幾乎所有的在線業務。除圖片之外,幾乎所有的動態內容都被它所服務,或者嚴格來說,圖片的有些信息也用它來存儲。越來越呈現一個趨勢,就是京東更多地用它來做主存儲,MySQL或者DataBase會進行歸檔。
接下來從技術角度做個簡單介紹。JIMDB基于redis,redis是一個非常優秀的開源軟件,它做對了兩個事情。第一,它是基于內存的,簡單且高性能;第二,也是基于內存,它提供了非常豐富的數據類型和數據結構。對許多互聯網公司來說非常方便,比如商品的詳情、屬性等,非常便捷。兩年前,京東為了解決它的痛點,因為之前的監控系統已不能滿足京東的業務需求,便不斷演進,一路做下來。

它是相對分散的分布式系統,有許多分支、模塊,不同模塊做不同的事情。從用戶(業務的開發人員)的角度,給他們提供Java、C driver,其他小眾語言是給他們提供代理,完全兼容但是不限于RAM servers 。對于任何一個業務都給它集群,所有集群都在京東的物理資源池上。京東這個團隊的核心任務是做一套復雜的平臺,一套健壯的分布式系統,管理目前大概四五千臺大內存機器,為眾多業務提供可靠的、性能穩定的、數據有持久性保證的高可用服務。
這個系統從部署結構來講,是單個物理服務器、多實力的結構,任何大內存物理servers上都會部署多個內存,好處是便于流量監控等,但是給業務和監控帶來很多復雜性。對行業來說目前還是比較合理,故障的檢測與切換,擴容的管理、升級、監控等都是獨立的模塊。存儲的servers是復用原來redis網絡編程的框架,但是復制的協議、存儲的引擎等各方面都是自己來開發。
在此列舉幾個技術點。第一,怎么做故障切換?分布式系統要解決的第一個問題是怎么處理故障。故障是個很嚴肅的事情,并不能簡單說有一個進程有一個servers不通了就是故障,會發生網絡不穩定等等,各個方面都有可能。在一個或多個數據中心有若干個故障檢測器,當多數人認為它故障并且沒有人認為它健康時,才能定位確實故障。發給故障的控制器做下一步事情,重新觸發新的配置,改變集群的拓撲。所以故障的檢測和自動的Failover是2014年做的第一個事情,把故障自動化,這個事情說起來簡單,其實是最基礎和最重要的,因為整個過程分很多步驟,前一段時間還出現過Bug。
第二個關鍵問題是任何一個邏輯的集群、業務數據量會增長、變化,所以必須支持在線、動態、重新的分片,或者說重新的Sharding,這個Sharding核心思想不是簡單把集群分片,中間要加一個抽象,才能進行動態的重新分片。對于這個策略來說,中間加一個bucket的抽象,然后來進行管理。遷移的過程是通過復制來做的,學術界或工程界喜歡管它叫“Partial replication”。舉例來說,原來是3個分片,現在怎么變成4個分片?通過調度算法,決策把哪些分片中的bucket遷移到這里,遷移是通過復制來做的,建一個復制關系,但是這個復制關系并不是復制它原來所有的數據,所以要求復制協議的實現是要做特殊的事情,只要這一個區間的復制,復制全部完成之后更改拓撲,最后生效,這可以做并行的Partial replication做遷移。從數據的可靠性保證比較高,技術也比較簡單和傳統。

過去兩年從底層技術研發分三個方面一步步演進做了些事情,從存儲引擎的角度,用的最多的是這個,第二個存儲引擎是LSM,京東用RAM+SSD做混合的兩級存儲,這三種不是取代的關系,而是互為補充。第二種更多應用的場景,是有些東西比較大,京東可以把這個放在SSD上,把K依然放在RAM里,這樣可以適當的節省成本,目前第二類線上已經有百分之十幾的用量,但是數據量要乘四五倍,因為每臺機器單機容量更大。第三類是B+TREE,可以排序,可以支持按范圍查找和便利,這個線上用得不是特別多,京東只支持有需要按范圍、需要便利查詢的場景。

復制協議更加關鍵,因為對于存儲來說最核心的是復制,除了異步復制就是同步復制,京東上半年做了狀態機的復制。分片策略京東用哈希最多,因為哈希最簡單,業務更多時候需要單K去查詢,有些業務需要按范圍,京東支持Range。這三個方面技術可以做合理的按業務場景組合,滿足不同的業務需求,比如業務更多是用Dict+異步復制+哈希分片策略,比較大的是RAM+SSD兩級存儲,然后配合其他的策略。
從業務使用場景角度,京東是分而治之,不同的軟件、不同的集群,根據業務的需要,可以分成這么兩大類。不少業務是做純緩存,后臺還有數據庫和其他存儲,京東更多是用異步復制或者不復制,哈希的分片,可以做LUR的淘汰。但是線上也有將近一半左右的集群,他們不僅僅用這個東西做緩存,他們做持久存儲,京東有更高的可靠性保證,一般用來開啟同步或者狀態機的復制,然后用范圍或哈希分片,而且對它的快照做定時備份,備份到內部對象存儲上去。
對任何一個系統來說,底層的基礎技術研發僅僅是它的一個環節,當系統達到一定規模之后,更多工作會放在監控和運維體系的建設方面。整個平臺京東有比較完善的監控體系,這更多是數據驅動的,從各個方面,連接樹、網絡入出流量等等,產生很多時間序列進行分析、預警,并且驅動各種控制器做決策。比如有的分片存的數據因為是個華為的手機,它太熱了,京東就可以把它做分列,很多時候做擴容做分列并不是因為容量,而是因為數據的熱度。數據監控也存在這個系統里做快速的展現。
基于容器的自動化運維,因為我剛才說過,整個系統規模比較大,有幾千臺機器,而且每臺機器上部署很多的存儲節點,所以運維的復雜性比較高。在整個2013年更多是依靠手工的運維,怎么樣選機器,怎么樣部署,運維工作量極大,在2014年下半年和2015年上半年,京東花了很長時間做全自動化運維的平臺,它是基于Docker,簡單來說是大的Linux大內存服務器上上面有很多Docker,每個進程是Docker實例,用Docker軟件管理版本,智能做機器的選擇,做定期的軟件升級,各個方面很多工作。這個平臺通過容器技術也在這里面有所發揮。
說一說規模吧,因為對于任何一個底層系統建設來說,它核心的價值只有一定規模、真實驅動業務才能有收獲力。線上京東有多個數據中心,有幾千臺大內存機器,都需要跨數據中心的復制,有的基于容災的考慮,比如不同的機房有不同的規則,有可能跨機房做異步復制,有可能同步,預計明年有512G內存或者1T內存機器的采購。線上支持了1000多個線上的業務,每個應用相當于一個邏輯的集群。從運維角度來說,這么多臺機器里面有大概3萬多Docker的實例。
內存存儲帶來什么?花了很多內存片、內存條,帶來了極佳的性能、非常穩定的性能,這是京東線上某一個比較重要的集群,在雙十一期間可以看到它整體的QPS超過200多萬,是非常穩定的,99%的請求都在2毫秒之內返回,這個讓用戶體驗更好,讓京東的業務開發起來更加簡單,讓公司運維團隊更加省心、更加輕松。
內存存儲考慮的一個主要因素是,內存可以花錢買,但是不能因為軟件因素再去浪費內存,內存存儲是分出來的,線上很多集群比較夸張、比較大,可能因為它使用場景比較特殊,才產生了碎片。但是整個分布來說,京東也做一些優化的工作,從內存分布器選擇來看,主要的集群內存碎片率基本在1.1-1.3左右。我個人工程上的經驗來說,這是非常好的內存分配器,內存分配器自行開發意義很小。
正在做的事情比較多,優先級比較高的是讓它更穩定更好的運維,除此之外進一步提升性能,通過軟件硬件協同創新,引入更大、更便宜的內存、更快的網卡,考慮重新實現用戶的網絡協議加速小包的處理性能。Linux網絡協議站不是為數據中心高速的網絡、高速的在線應用而設計,每一次包都要中斷,對于大包是合理的,對于小包是不劃算的,這樣的存儲性能更多的是小包處理,京東在考慮重寫用戶協議,來加速小包處理的性能。在功能方面京東也在做個事情,這更多是工作量的事情,考慮從NoSQL支持SQL接口,因為底層有了橫向擴張、靈活復制的內存里的數據結構的存儲。通過JAVA等等提供,這是工作量的問題而已。
另外,希望在某種程度上降低成本,因為平臺化第一步是求規模穩定,讓它有很好的性能和效率的保證,第二是從整體來說能降低成本,比大家分散、自由去用更省錢。基本的想法是這樣的,目前是專署集群,京東希望從專署集群過渡到聚合各個IDC的RAM資源,比如說京東私有云機器去分容器、去分虛擬機,很多時候CPU是瓶頸,分完了內存有剩余,非結構化機器磁盤是瓶頸,磁盤或SSD被分完了但內存有空余,京東聚合整個RAM資源,讓數據動態流動、去降低成本。
云數據庫服務是一項基礎性的云服務,解決用戶自己搭建數據庫時需要考慮的各種問題,讓用戶在使用時可以按需申請數據庫資源,保證整個數據庫服務的穩定性及數據的可靠性,同時提供彈性伸縮等的支持,盡可能的降低用戶在使用云數據庫時的成本。
本主題主要是分享京東私有云分布式數據庫集群的實現,包括如何支撐上億級數據量的業務,如何保證數據高可靠、服務高可用以及在線集群擴容等機制。另外還會分享京東公有云數據庫的架構與設計,如何實現一個穩定、可靠、可彈性伸縮的公有云數據庫服務,涉及到備份、恢復、監控、遷移、高可用切換等一整套方案。
京東內部有大量業務的數據是存放在Oracle中的,為了完成京東內部去O的過程,京東為此打造了一套私有云分布式數據庫集群,這套私有云分布式數據庫集群目前支撐著京東大量擁有上百億級數據量的業務,本主題中會重點介紹去O過程中遇到的難點同時詳細介紹在內部數據庫云化以及在支撐大規模業務過程中積累的經驗,包括如何打造一套高性能的私有云分布式數據庫集群服務,如何在支撐京東上百億級別數據量業務正常服務的情況下做到在線無縫集群擴容,分享來自京東生產一線的經驗。
云服務最重要的是要做到可彈性伸縮可按需獲取資源,讓用戶可以盡可能的花最少的代價滿足業務的需求。用戶使用云數據庫時面臨當業務量增長時申請的資源不夠,需要做到快速的擴張現有資源,當業務量降低時需要快速縮小現有資源。當數據庫實例甚至整個機房發生故障時,要做到用戶在云數據庫中的數據是安全的可靠的,可以第一時間恢復云數據庫服務,包括跨機房恢復等,保證云上的用戶業務是不受影響的,這些都是云服務尤其是云數據庫服務需要解決的事情,本主題也會介紹京東公有云數據庫是怎么解決這些問題的以及在解決這些問題時積累的經驗。
京東云數據庫主要包括公有云數據庫服務和私有云數據庫服務兩部分。公有云數據庫主要是面向外部用戶,定位是中小型公司;私有云數據庫主要針對公司內部業務,有時候甚至會特殊業務特殊對待,會針對業務的特點來具體問題具體分析,數據量較大的業務京東會建議業務使用京東私有云分布式數據庫集群,將數據進行拆分等。這兩項服務在京東都是由同一個團隊來提供支持,京東云數據庫的總體做法是將私有云數據庫中積累的經驗逐步的輸出到公有云數據庫上。
云數據庫集群服務主要是指分布式數據庫集群,用戶在使用這個集群的時候可以像使用單臺數據庫一樣去使用,在業務層面不用關心集群中的數據是如何分布的,對用戶來說后端的數據庫實例是不可見的或者不需要關心的,在使用層面來說心智負擔會大大降低。
N個數據庫同時提供服務一般是指N個數據庫服務多個不同的業務,或者是某個業務同時使用了N個數據庫,但是業務對這些數據庫是有感知的,換句話說這N個數據庫對業務都是可見的。
云數據庫服務其實也可以理解為將傳統的數據庫服務搬到云上,但是云數據庫服務尤其是公有云數據庫和傳統的數據庫確實是有區別的,最大的挑戰在于不僅僅要提供數據庫服務,還需要與用戶的私有網絡及云主機甚至包括云存儲等各項云服務相互配合提供高可用的服務、保證數據的高可靠,是一整套云服務中的一項。傳統的數據庫技術更多關注的是數據庫本身的,網絡及主機等問題一般會比較簡單。
京東公有云數據庫的架構都是基于私有云數據庫的實踐經驗所得,在實際輸出的時候考慮到安全及彈性伸縮等的考慮,公有云上采用基于虛機部署的方式,結合云主機云存儲以及云數據庫系統自身相配套的信息采集系統再整合公司的監控系統等各項服務,對外提供可伸縮高可用及高可靠的公有云數據庫服務。
私有云中的分布式數據庫集群架構主要是采用引入中間件的方式來支撐業務,中間件本身完全兼容mysql協議,在內部業務使用的時候可以像使用原生數據庫一樣簡單。
公司內部有一套完整的統一的監控系統,云數據庫自身還有一套信息采集系統,采集系統會采集數據庫實例上的相關信息包括慢查詢以及機器負載等信息,這些采集的信息經分析處理以后如果如果發現有異常比如有慢查詢或者機器負載較高,會通過統一的監控系統觸發報警,做到及時發現問題及時處理問題。
在私有云分布式數據庫集群中的性能監控主要是兩部分構成,一部分是分布式數據庫中間件會對查詢做一些統計信息,這些統計信息中有超過某些閾值的情況就會觸發報警,另外一部分是數據庫本身的完善的監控系統。
京東公有云數據庫目前是部署在虛擬機里的,基于虛擬機的快速創建京東可以做到公有云數據庫實例的較快的創建。私有云數據庫目前有很大一部分已經將數據庫實例放到容器里,在創建部署方面將更加的便捷,當內部驗證以后后續京東也會考慮輸出到公有云上。
京東的業務發展非常的迅猛,所以在很大程度上來說京東的技術都在被業務驅動著往前跑,很多業務早期數據可能是放在Oracle或者Sqlserver中的,等到業務量比較龐大的時候再著手將數據從原來的數據庫遷移到mysql里的時候就會比較痛苦,一般都需要業務方和數據庫團隊緊密配合才能真正的完整的遷移出來,但是也正是因為有這些實際的業務需求驅使著京東的技術不斷的提升。