我們一起聊聊分布式數據服務
目標
數據存儲資源是系統中最重要的組成部分,數據即一切,尤其分布式領域,主要關注以下幾點:
- 高可用性,當遇到網絡或者系統故障時,系統仍然保持可用
- 高擴展,當數據規模變大時,數據存儲系統能夠自動適應這種變化
- 高性能,當數據規模和訪問規模變大時,性能不受大的影響
- 成本,通過成本反映出系統設計是合理的
- 安全,遇到各種系統和人為故障時,數據不丟失
MySQL
MySQL是OLTP關系型數據庫,支持ACID事務,是最主要的存儲系統,目前使用的版本是5.7。
MySQL本身不是分布式系統,其支持的數據復制技術,本質上是為了數據容災使用,但目前基于主從復制進行讀寫分離,減少單機的讀壓力。
MySQL服務如果托管在阿里云,可以使用高可用版本,秒級的主從切換,基于云盤的磁盤擴容技術,能夠快速復制一個只讀節點,減少了很多自建MySQL遇到的各種問題,另外其還提供了很多額外的功能,比如索引分析、SQL審查、慢查詢分析、動態擴容。
雖然云托管RDS,但本質上還是MySQL,仍然會遇到很多問題,比如:
- 數據存儲不支持分片,只能通過分庫分表的方式進行橫向擴展,目前應用層也不支持分庫分表的路由,即使分表,拆分表的時候還是會遇到很多問題
- 如果表設計和索引設計不合理,大量的更新,仍然會遇到主從延遲的問題,從應用層面是很難徹底解決的
- 阿里云RDS只支持一個負載均衡主從分離,所以后臺、隊列應用使用360 Atlas讀寫分離服務,目前是一個單點,且也會影響讀寫性能。
- MySQL應用規范目前還沒有建立,比如什么樣的應用應該選擇MySQL,使用MySQL很大程度是為了事務,如果沒有事務的場景是否可以選擇其他的數據庫?
- 阿里云官方提到,單表記錄數超過500w,性能會極具下降
- DDL操作,尤其對于大表操作,會引起很大的同步延遲問題
云托管的RDS本質上還是基于ECS+云盤搭建的,數據的增長、備份、性能、遷移、升級、只讀實例、磁盤容量、Binlog延遲還是會顯露出來。
那未來如何?其實云廠商也在探索,提出了云原生數據庫、云原生分布式數據的概念,比如阿里云的PolarDB、PolarDB-X。
云原生數據庫關注成本、性能、在線業務擴展、數據安全,它的核心技術包括計算和存儲分離,物理復制Binlog行復制模式,共享存儲設備,存儲之間通過RDMA高速網絡協議傳輸,同時PolarDB-X支持分區模式,解決了分庫分表的問題。
經過這些創新,傳統MySQL的弊端被解決了,比如同步延遲、備份、成本、分庫分表、性能。
未來,可以將核心數據庫遷移至云原生數據庫,保障核心業務的穩定性和擴展性,而對于非OLTP業務可以選擇其他數據庫,且制定MySQL應用規范,明確哪些業務模式使用MySQL,索引正確設計、容量規劃、SQL語句使用規范等等。
Redis
Redis是K/V數據庫,它基于單線程、內存操作,所以性能非常高。另外支持豐富的數據結構,比如字符串、Hash、List、集合,應用場景非常廣泛。
它通過AOF和RDB保障數據持久化,通過復制技術進行數據備份,也支持通過哨兵和分區提供高可用性和容量伸縮,通過LUA腳本支持多條命令的事務操作。
Redis雖然是一個單機系統,但通過復制、集群技術也可以認為是一個分布式存儲系統,目前西五街在大量使用,主要分為三類應用:
- 存儲,比如用戶積分、文章數等數據,這些數據不能丟
- 緩存,比如用戶文章列表數據,需要考慮緩存穿透和雪崩等問題
- 消息隊列,目前逐步替換為Kafka等純消息系統
阿里云云托管Redis社區版5.0服務集群版。
在應用設計上存在以下幾個問題:
- 存儲和緩存混合使用,無法拆分,對于容量估算不透明
- 應用模式上,沒有很好的規范,比如緩存更新機制標準、統一Lib應用包
通過阿里云Redis提供的部署架構,可以很好的理解它的應用場景:
- 標準版-雙副本:服務可靠,數據可靠,比較標準的使用模式,不管是存儲還是緩存服務都可用
- 集群版:通過代理模式和分片可以構建出一個可伸縮的集群模式,解決Redis自身單線程瓶頸,滿足大容量、高性能的業務需求,而且副本集主要做恢復用,很適合存儲場景,不存在同步延遲的問題
- 讀寫分離架構:對于不關注同步延時的問題,比如緩存場景,可以選擇這種模式,當容量不夠的適合,通過客戶端的一致性Hash技術擴容多個Redis實例就可以
后續確定Redis使用規范,拆分存儲和緩存場景,基于統一Lib包,就能解決大部分問題。
Elasticseach
Elasticseach是一個近實時的分布式搜索引擎和分析引擎。
作為一個搜索引擎,目前在開源領域已經是排名第一的數據庫了;基于倒排索引,具有很強的檢索能力,所以不管是應用還是在大數據領域,它都是一個非常通用的分析引擎。
近實時表示Elasticseach應用場景必須要有所了解,它不支持ACID,所以無法是一個OLTP數據庫,但使用壓力小了很多,在做策略分析、后臺應用、即時查詢上有很廣泛的場景。
作為一個分布式應用,通過副本集機制解決高可用的問題,能夠解決單機故障的問題,但如果數據被誤刪除,還是需要有備份機制,比如Elasticseach的快照機制。
副本集的同步最終達到一致性,為了寫入性能,也可以配置主節點寫入完成即返回給客戶端。
在容量可擴展方面,可以采用分片機制解決容量橫向伸縮的問題,將數據分到不同節點的不同分片上,如果要調整分片,需要reindex。
在性能方面,通過多副本集節點分擔查詢壓力。也可以使用專門的Transport節點分擔date Node節點的壓力,將分片查詢,副本查詢等路由和合并動作的結果匯總起來。
Elasticseach是ELK解決方案的一部分,其還包括很多服務,包括Filebat,Kibana,Logstash,在大數據領域也是很好的一個方向。
Elasticseach是在ELK上搭建的三節點服務,由于規模問題,目前也很少使用分片技術。核心是文章大寬表,用戶大寬表。
結合了搜索場景和分析場景,通過Binlog+Canal+Kafka+Go服務將MySQL多個表匯總到一個大寬表,主要是文章信息的大寬表,一方面是滿足搜索場景,另外滿足策略和應用場景。
現在大寬表的應用模式非常多,基于Free Schema模式,查詢模式非常靈活,通過訂閱方式同步數據,也減輕了應用層的負擔,數據正確性有很大的保障。
未來,對于Elasticseach的應用,一方面要加強性能調優,比如分片數據的不均勻,查詢性能的優化,同時要提升可維護性,比如挖掘reindex、alias等功能,充分理解Elasticseach。
而在國內的云廠商中,都沒有對Elasticseach做太大的升級,基本上就是將Elasticseach服務托管到云中。
Kakfa
Kakfa是一個分布式的高吞吐消息隊列,訂閱/消費模式追求的是高性能,而非存儲容量。但其日志本身具有重放功能,也可以理解為一個分布式存儲系統。
Kafka的核心功能包括:解耦、消峰、緩存,應用場景極為廣泛,是系統不可缺少的一個組件。
作為分布式系統,它也有副本和分區機制,從而保障高可用和高吞吐。通過segment順序寫,保障了寫性能非常高,而基于消費組組的概念,消費者吞吐能力也能橫向擴展。同時每個broker都能負責查詢,提升了吞吐能力
Kafka基于Zookeeper做很多分布式管理功能,包括Leader選舉,負載均衡,Meta存儲。
目前Kafka三節點集群是通過ECS自行搭建的,運行近一年,服務相對穩定,可維護性也較好,沒有太多的管理工作,很多核心服務都已經使用了Kafka隊列,后續原有基于Redis的隊列也可以盡快遷移。
MongoDB
MongoDB是一個分布式的文檔數據庫,其目標是一個支持ACID事務的分布式數據庫,因為是面向文檔,所以模式非常靈活,結構松散,使用場景很規范,相比MySQL,其二進制的存儲模式,壓縮比非常高,存儲成本會大幅減少,同時基于WiredTiger引擎,能夠創建各種類型的索引,甚至子文檔也能創建索引,從而提升查詢性能
MongoDB通過oplog技術支持副本集,也支持分區,分區鍵可以自定義,因為有了分區,所以額外有了mongos路由服務器,config服務器,mongos路由服務器通過查詢config服務器,向節點和分區發送服務。
MongoDB將一致性和性能訴求交給了客戶端,通過read concern、write concern、read perference技術提供多種靈活性,比如你要求強一致性,那么就采用majority,你要求數據永遠不丟失就配置journal為真。
MongoDB 4.0和MongoDB 4.2支持多文檔的事務,分別支持復制集、分區維度的事務性,但使用和理解非常復雜,可能是分布式系統中最難學習的部分。
這樣說明,不用刻意使用事務,對MongoDB進行良好的建模,做OLTP關系數據的補充,其在性能、成本、高可用、伸縮性方面是有優勢的。其實在MySQL中,目前我們也很少使用跨表,跨語句的事務,所以不要太迷信事務,選擇好應用場景。
除了查詢,MongoDB也支持各種聚合操作,在分析領域也很有廣泛的使用場景,這一點和Elasticseach很類似。
目前MongoDB三節點集群是通過ECS自行搭建的,存儲規模較小,使用場景較少。
對比MySQL和Elasticseach,MongoDB還是有很廣泛的應用場景,比如分析場景,對事務要求不高的場景,數據增長比較大的場景(比如私信數據),業務模式比較靈活的場景(比如各種條件的查詢,聚合操作)。
不過和Elasticseach一樣,各大云廠商一樣,只是將這個服務托管到云,并沒有做太多的優化。