【DIY】基於共享內存的數據庫映射

基於共享內存的數據庫映射

概述

隨着各類行業軟件對性能追求越來越高,因此對數據庫處理的速度提出了新的挑戰。然而大部分複雜的業務處理往往依賴體量較大的關係數據(如:Oracle,Mysql,PostgresSQL等),雖然這些關係數據庫的功能已經足夠的強大,但這些數據庫的性能方面在某些場合又未必能滿足我們的要求。因此,一些NOSQL的數據庫(如:Redis、MongoDB、LevelDB等)逐漸佔領了一部分市場。同時內存數據庫(如:Sqlite、Oracle TimesTen、eXtremeDB等)也被廣泛的使用。

本文主要討論,將關係數據庫中的數據映射至(共享)內存,然後在內存中對其進行操作。使用共享內存方式和OCI/OCCI接口對ORACLE數據庫的表或視圖進行內存映射,當然也不侷限於ORACLE數據庫,理論上是可適用大部分關係數據庫,甚至結構化的文件(CSV,XML,JSON等)。同時,共享內存的使用爲多進程共享業務數據提供了基礎。

共享內存

提到共享內存就要先說說Linux進程間通信(IPC:InterProcess Communication)

,linux下的進程通信手段基本上是從Unix平臺上的進程通信手段繼承而來的。進程通信的目的主要是,傳輸數據、資源共享、進程控制等。常用的進程間通信手段包括:管道、信號、消息隊列、共享內存、信號量、套接字(SOCKET)等。

共享內存是在多個正在運行的進程之間傳遞數據的一種非常有效的方式。共享內存的具體實現是不同進程共享的內存分配同一段物理地址,如下圖:

如圖所示,進程1的邏輯地址空間和進程2的邏輯地址空間映射到同一塊物理內存,從而實現該內存上數據的共享或數據傳遞。

相關函數:

int shmget(key_t ey,size_t size, int shmflg);

創建共享內存

void *shmat(int shm_id, const oid *shm_addr, int shmflg);

將共享內存連接到進程

int shmdt(const void *shmaddr)

斷開共享內存連接

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

共享內存管理

 

1.2 OCI/OCCI

Oracle 調用接口 (OCI) 是最全面、性能最高、基於原生“C”語言的 Oracle 數據庫接口,它可以提供 Oracle 數據庫的全部功能。OCI 爲構建各種語言專用接口(如 Oracle JDBC-OCI、http://ODP.Net、Oracle 預編譯器、Oracle ODBC 和 Oracle C++ Call Interface (OCCI)驅動程序)提供了基礎。

OCCI是基於OCI的Oracle數據庫的C++接口,是對OCI的進一步封裝,簡化了接口調用,提供了更加優化的用戶適用體驗。

出於性能和穩定性的考慮,該工程將以OCI作爲接口的技術選型。

系統模型

整體模型

根據功能與依賴關係將系統模型分爲四個層次,分別爲:持久化成、內存數據層、邏輯層、應用層。並且上層對下層具有依賴關係,每一層通過接口進行解耦,如下圖所示:

 

 

 

持久化層

持久化層作爲永久存儲數據媒介,同時也是內存數據映射的來源。

 

 

持久化形式可以是關係數據庫,K-V數據庫或格式化文件。該層對外提供兩個主要的接口,LoadData()和WriteBack(),類結構如下圖:

 

 

 

爲上一層“內存數據層”提供數據接口。

內存數據層

該層使用共享內存方式提供數據,可爲多個進程通過數據共享,內存結構包括:

 

 

  1. 共享內存頭,存儲共享內存的基本信息,如:共享內存名、IPCKEY、內存塊大小、創建時間,以及進程塊和表信息塊的首地址偏移量。該區域是共享內存數據使用的入口,可以方便的得到進程信息的偏移量,表信息的偏移量。
  2. 進程信息,當進程鏈接(attach)到共享內存區域時,會將該進程的信息寫入進程信息區。寫入信息包括:
  1. 進程組號:標識進程所屬的組,比如,管理進程/業務進程/監控進程/回寫進程。
  2. 進程ID:進程的邏輯編號非系統PID,是進程在進程組內的唯一標識。
  3. 進程啓動時間:進程啓動並鏈接到共享內存的時間。
  4. 進程狀態:進程當前的狀態,比如,運行/停止等。

 

 

  1. 表信息,是對關係數據庫或結構化文件數據的二維抽象即“表”,由Load進程將持久化層的數據信息和數據內容加載到共享內存中。數據“表”信息包括:表名、文件名(內存映射文件)、最大記錄條數、單條記錄大小、只讀標誌、告警百分比、回寫標誌、數據首地址等信息。
  2. 數據域,存放表數據的內存段,當Load進程向共享內存加載數據時,根據單條記錄的大小和記錄最大條數等信息,計算出表數據的偏移量,並根據偏移量得到表數據的存儲首地址,將數據依次存入表數據區。該區域爲上一層“邏輯層”提供數據訪問。

內存數據層關鍵數據接口如下:

 

 

對上層提供主要接口爲IDataManager,這裏只實現了CShmManager,即基於共享內存的數據存儲,當然也可以實現普通內存的實例。

 

 

邏輯層

邏輯層的主要目的是爲應用層提供方便靈活的數據操作接口,該層提供了各種數據操作的封裝,可以是基於sql的標準查詢語言,也可以是基於容器的操作,從而實現內存數據的增、刪、改、查等操作。

如下圖:

  1. CDAO爲邏輯層提供的入口。
  2. CDML是接口類,提供了數組操作的基本接口。
  3. CIndex,對錶操作的索引封裝。
  4. CKey,索引鍵值封裝。
  5. CSqlTools,sql操作的封裝,支持標準sql進行數據操作。
  6. CSqlBase,標準sql封裝,使用flex/bison進行語法解析和此法解析,爲CSqlTools提供基本操作。
  7. ContainerTools,基於容器的K-V數據操作。
  8. CShareMemory,指向共享數據層的共享內存數據封裝。

 

 

2.5應用層

應用層爲用戶提供API,應用進程通過API可以實現共享數據操作接口。比如實現業務的業務進程、監控進程、管理進程等。

API入口CFrameWork,提供InitFrameWork(),Connect(),DisConnect()等接口。

3總結

上文描述了將數據庫或結構化文件的數據映射至(共享)內存的數據模型,由於篇幅原因精簡了實際工程的數據結構。整體模型由低到高分爲四個層級,簡述了數據加載至(共享)內存,通過內存數據建立內存數據庫(實現增、刪、改、查功能),提供應用層API接口,建立應用進程,最終共享內存數據的過程。

發佈了51 篇原創文章 · 獲贊 12 · 訪問量 5154
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章