信息管理類應用系統離不開關係數據存儲,目前大家基本都使用的是傳統的資料庫如MySql、Postgres等。作者從事信息化建設十多年,個人認為傳統的資料庫存在以下的問題: 擴展問題: 系統數據的不斷增長是個繞不過去的坎,傳統資料庫的存儲結構一般 ...
信息管理類應用系統離不開關係數據存儲,目前大家基本都使用的是傳統的資料庫如MySql、Postgres等。作者從事信息化建設十多年,個人認為傳統的資料庫存在以下的問題:
擴展問題:
系統數據的不斷增長是個繞不過去的坎,傳統資料庫的存儲結構一般都基於B+tree,單表數據在一定範圍內沒有問題,但數據量增大到一定程度後性能便會不斷下降,只能通過分庫分表的方式或升級硬體來解決,隨之而來的是提高了應用軟體的開發難度及相應的硬體成本。作者曾建設過一個北斗監控平臺,其中單表記錄10多億,經過優化雖能實行秒級查詢一天軌跡,但備份及定期刪除歷史數據非常慢且影響線上操作,後來只能手工實現了一套文件存儲來解決(那個時代還沒有NoSql)。
可用性問題:
傳統資料庫只能使用主從的方式來保障可用性,運維較複雜。作者曾經碰到過一次閃電導致機房(等保三級)內一臺資料庫用SAN存儲的電源背板燒壞,雖這台存儲冗餘電源,RAID10統統沒用,導致系統停用兩天。
開發人員問題:
由於開發人員對sql的熟悉程度不同,經常能碰到寫的很爛的sql語句。另外如果使用ORM,則ORM->Sql字元串->網路傳輸->Sql引擎分析->執行->網路傳輸->ORM存在較大性能損耗。作者的一個朋友在一家公司做運維,他說他公司的開發只管程式能否跑通,從不管sql優化問題,導致系統很慢,出了問題全丟給運維處理。
由於存在上述問題,作者一直在尋找新的適合於信息管理類系統的存儲技術,既能簡單的隨需擴展,又能保障高可用高性能,還能兼顧大數據存儲與分析,最好建設與運維的成本儘可能的低(作者接觸的都是中小微企業)。因此先後學習了互聯網企業常用的NewSql(TiDB, Cockroach)、NoSql(Cassandra, Kudu, ES等)技術,希望能將這些技術應用於傳統的信息管理系統的建設。但隨著進一步的深入瞭解,這些技術都存在這樣或那樣的問題,比如或架構複雜問題,或事務一致性問題,或性能問題(如併發扣減庫存)。
在學習了上述技術的原理後,作者就想能否重新實現一套適合於上述要求的分散式資料庫,直接集成至應用框架內,從而可以:
簡化應用系統架構
整個應用系統由一個或多個節點組成,每個節點負責處理用戶請求及存儲,隨需擴展節點。
表分區
大表支持定義為按分區鍵分區存儲(類似於Cassandra的PartionKey),同時支持分區索引及全局索引,以避免熱點問題,另外刪除整個分區對性能的影響較小。
強一致性事務
基於Raft及2PC支持分散式事務(類似於TiDB, Cockroach)。
簡單的Api
支持框架的實體模型與存儲結構的直接映射,避免sql字元串轉換與分析損耗,另由於直接進程內訪問存儲引擎,可減少網路通信開銷。
舉個簡單的保存例子:
var pos = new Entities.VehiclePosition(vehicleId); //車輛位置,根據id分區
pos.LAT = 32.22223;
pos.LNG = 100.2123;
await EntityStore.SaveAsync(pos);
再舉個簡單的表掃描查詢例子,支持其他查詢方式如索引掃描,聚合掃描等:
var q = new TableScan<Entities.VehiclePosition>();
q.Partions(p => p.VehicleId == vehicleId); //指定分區條件
q.Filter(t => t.CreateTime >= startday && t.CreateTime < endday); //指定分區內記錄過濾條件
var list = await q.ToListAsync(t => new {t.Id, t.LAT, t.LNG}); //選擇指定列
小Tip:
- 在實現表掃描及聚合掃描時,作者利用C#的Emit直接生成條件過濾代碼,類似於PG10 llvm生成代碼。
- 關於Join將只支持LeftJoin,複雜Join只能在服務代碼內利用C#的Linq處理。
- 目前事務隔離級別隻支持ReadCommitted及Seializable,但純讀支持本地讀、線性一致性讀、事務讀。
目前作者還在不斷踩坑與嘗試實現上述目標,當然首先要感謝上述所提的那些技術先驅們,在此希望有志同道合者來共同完成它。已實現的技術原型參考前篇
AppBoxFuture(一): Hello Future!,下篇“分而治之”將介紹框架如何在較低的硬體下保障高性能。