亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        基于內存映射文件的復雜對象快速讀取方法

        2020-04-09 06:36:40黃向平彭明田楊永凱
        計算機技術與發(fā)展 2020年3期
        關鍵詞:進程嵌入式數(shù)據(jù)庫

        黃向平,彭明田,楊永凱

        (1.中國民航信息網(wǎng)絡股份有限公司,北京 101318;2.民航旅客服務智能化應用技術重點實驗室,北京 101318)

        0 引 言

        后臺高并發(fā)高性能系統(tǒng)設計過程中,經(jīng)常碰到數(shù)據(jù)訪問寫少讀多的場景。比如民航航班運價搜索平臺,航班運價數(shù)據(jù)更新不頻繁,但搜索過程需讀取并處理大量復雜數(shù)據(jù)。如何解決復雜數(shù)據(jù)讀取效率的問題,是系統(tǒng)性能優(yōu)化的關鍵問題之一。

        Linux環(huán)境下高并發(fā)高效率的數(shù)據(jù)訪問技術有NoSQL內存數(shù)據(jù)庫[1]、嵌入式數(shù)據(jù)庫[2]等。NoSQL(not only SQL)內存數(shù)據(jù)庫典型代表有redis[3],它是一種key-value類型的數(shù)據(jù)庫產品,在大數(shù)據(jù)平臺[4]、緩存系統(tǒng)[5]中得到了廣泛的應用,相對于關系型數(shù)據(jù)庫,具有服務響應快、并發(fā)訪問高、易于擴展、易于開發(fā)等優(yōu)點。嵌入式數(shù)據(jù)庫是一種輕量級的、與應用進程在同一個地址空間的數(shù)據(jù)庫,Berkeley DB是目前應用較廣泛、較穩(wěn)定的技術選擇,不但適用于嵌入式系統(tǒng),也同樣適用于高性能后臺服務系統(tǒng)[6],優(yōu)點是不需要進程間通信,讀取效率很高。

        對上述兩種高性能數(shù)據(jù)庫的研究發(fā)現(xiàn),當數(shù)據(jù)結構復雜、讀取頻繁時仍會有性能問題。鑒于此,文中提出了基于內存映射文件的復雜對象快速讀取方法。主要從三個方面對讀取過程進行改進:(1)通過內存映射文件[7],省掉了內核態(tài)到用戶態(tài)的內存拷貝操作,從而提高數(shù)據(jù)讀取效率;(2)優(yōu)化文件內數(shù)據(jù)格式,無需轉化即可直接使用,從而提高數(shù)據(jù)格式轉化的效率;(3)復用模板庫和容器,避免重新編碼實現(xiàn)一些常用數(shù)據(jù)結構,從而提高開發(fā)效率。

        1 傳統(tǒng)數(shù)據(jù)庫技術

        1.1 內存數(shù)據(jù)庫

        近年來,隨著計算機技術的不斷發(fā)展,特別是互聯(lián)網(wǎng)應用的擴張普及,對于高并發(fā)環(huán)境下的數(shù)據(jù)庫技術提出了高可用、高性能的要求。在一些諸如交通、電信、金融、電子商務之類的應用中,對于響應時間有非常高的要求。當前隨著半導體技術的發(fā)展,摩爾定律依然有效,內存芯片的價格不斷降低,服務器內存存儲容量已經(jīng)向TB級別邁進。相應的64位CPU和Linux操作系統(tǒng)的普及,操作系統(tǒng)尋址空間達到了2的64次方。內存資源緊張昂貴的歷史一去不復返,如何充分、有效地利用內存資源成了軟件設計的重點。因此,對于那些數(shù)據(jù)訪問實時性要求很高的應用來說,開始考慮把整個數(shù)據(jù)庫或者部分數(shù)據(jù)存儲于內存之中,從而產生了內存數(shù)據(jù)庫的概念。

        一般定義上的內存數(shù)據(jù)庫,是指數(shù)據(jù)常駐內存,在數(shù)據(jù)讀寫執(zhí)行過程中沒有內外存之間的數(shù)據(jù)I/O,顯然,它需要較多的物理內存,但也不一定把整個數(shù)據(jù)庫置于內存當中。和傳統(tǒng)的基于機械磁盤來存儲數(shù)據(jù)的數(shù)據(jù)庫系統(tǒng)相比,擁有更快的數(shù)據(jù)讀寫速度,因為內存數(shù)據(jù)庫在指令執(zhí)行過程當中沒有磁盤讀寫操作。同時,內存I/O性能遠高于磁盤,所以基于內存的數(shù)據(jù)庫讀寫性能也遠高于傳統(tǒng)磁盤數(shù)據(jù)庫。

        典型的內存數(shù)據(jù)庫如memcached和redis,是一種nosql數(shù)據(jù)庫,也是一種鍵值對數(shù)據(jù)庫。通過在內存里維護一個統(tǒng)一的巨大的哈希表,能夠存儲各種格式的數(shù)據(jù)。一般的使用方法是減少數(shù)據(jù)庫訪問次數(shù),以此提高系統(tǒng)服務響應時間,也可以把全量數(shù)據(jù)存儲于內存數(shù)據(jù)庫當中,完全替代傳統(tǒng)關系型數(shù)據(jù)庫。通常情況下,受制于物理內存空間大小,在數(shù)據(jù)容量達到指定值后,系統(tǒng)就基于LRU(least recent used)算法[8]自動刪除不適用的數(shù)據(jù)。可以說這類內存數(shù)據(jù)庫是為緩存而設計的服務器,并沒有過多考慮數(shù)據(jù)的永久性問題。不過redis加入了virtual memory改進方案,把很少使用的value保存到磁盤,而所有key保存于內存當中。因此redis可以應用于海量復雜數(shù)據(jù)的高性能讀寫場景。

        此類內存數(shù)據(jù)庫是基于epoll網(wǎng)絡事件處理模型的C/S服務架構,支持高并發(fā)的網(wǎng)絡連接,充分利用了網(wǎng)絡I/O能力。如果把客戶端與服務端部署于同一臺服務器,則能避免網(wǎng)絡延遲,只需進程間通信即可完成數(shù)據(jù)訪問,提升響應速度。

        1.2 嵌入式數(shù)據(jù)庫

        嵌入式數(shù)據(jù)庫通常與嵌入式操作系統(tǒng)及具體的應用集成在一起,無需獨立運行數(shù)據(jù)庫服務實例,由程序直接調用響應的API即可讀寫數(shù)據(jù),不需要對某種查詢語言進行解析,也不需要生成解析計劃。不僅僅適用于嵌入式操作系統(tǒng),在一些高性能系統(tǒng)當中也直接連接嵌入式數(shù)據(jù)庫,和應用程序運行在同一個地址空間,避免了進程間通信的消耗,因此具有較高的運行效率。

        Berkeley DB是目前使用較多的一種嵌入式數(shù)據(jù)庫,作為一種輕量級嵌入式數(shù)據(jù)庫,為許多編程語言提供了API接口,包括c、c++、java、python等,所有數(shù)據(jù)庫相關操作都由Berkeley DB庫函數(shù)負責統(tǒng)一完成。這樣在多進程讀寫并行訪問,或者在同一個進程內多線程競爭訪問,都可以保證數(shù)據(jù)的一致性、完整性。底層的數(shù)據(jù)加鎖、事務日志和存儲管理等都在Berkeley DB庫函數(shù)中實現(xiàn),它們對于應用程序而言是完全透明的。

        Berkeley DB對于任何存入的value數(shù)據(jù)都是原樣拷貝到數(shù)據(jù)文件當中,無論是文本數(shù)據(jù)還是二進制數(shù)據(jù)。它提供了四種存儲數(shù)據(jù)的模式:btree、hash、queue和recno,在打開數(shù)據(jù)庫的時候,需要指定其中一種存儲模式。雖然有多種存儲模式,但鍵值對是數(shù)據(jù)庫的基礎數(shù)據(jù)結構。用API函數(shù)訪問數(shù)據(jù)庫時,只需提供關鍵字就能夠訪問相應的數(shù)據(jù)。鍵值對結構在Berkeley DB中都是用一個名叫DBT的簡單數(shù)據(jù)結構來表示的,它的作用主要是保存相應的內存地址和長度。

        1.3 數(shù)據(jù)傳輸轉化過程

        數(shù)據(jù)的讀取過程,就是數(shù)據(jù)從數(shù)據(jù)庫傳輸?shù)綉眠M程,并轉化為運行時數(shù)據(jù)結構的過程。為了獲得比傳統(tǒng)內存數(shù)據(jù)庫、嵌入式數(shù)據(jù)庫更高讀取性能的讀取方法,在此分解研究數(shù)據(jù)傳輸轉化過程,并依此提出優(yōu)化目標對象。

        進程地址空間分為內核態(tài)和用戶態(tài)[9],其中內核態(tài)地址空間為所有進程與內核共享,用戶態(tài)地址空間為每個進程獨有。不管是跨網(wǎng)絡、跨進程,還是讀取文件的數(shù)據(jù)傳輸方式,都涉及到內核態(tài)數(shù)據(jù)拷貝至用戶態(tài)的過程。具體過程如圖1所示。

        圖1 數(shù)據(jù)庫數(shù)據(jù)傳輸轉化過程

        (1)內存數(shù)據(jù)庫有獨立運行的數(shù)據(jù)庫引擎實例,數(shù)據(jù)依賴網(wǎng)絡傳輸,數(shù)據(jù)包到來后網(wǎng)卡通過DMA將數(shù)據(jù)送入內核態(tài)地址空間,交由內核協(xié)議棧來處理,用戶進程通過系統(tǒng)調用拷貝該數(shù)據(jù)包至用戶態(tài)地址空間。如果內存數(shù)據(jù)庫與用戶進程部署于同一臺服務器,則通過Linux回環(huán)接口(loopback)傳輸,它是一個虛擬網(wǎng)絡接口,不與任何硬件相連,數(shù)據(jù)包的傳輸不經(jīng)過網(wǎng)卡直接送入內核態(tài)地址空間,之后的協(xié)議處理傳輸與網(wǎng)絡過程相同。

        (2)嵌入式數(shù)據(jù)庫把數(shù)據(jù)存儲于數(shù)據(jù)文件當中。為了避免頻繁重復的磁盤訪問,Linux操作系統(tǒng)在內核態(tài)地址空間內存里維護了一個頁面緩存(page cache)[10],這樣在從磁盤讀取文件內容前查找這頁面緩存是否已經(jīng)裝載了,只有沒有命中緩存時才真正的從磁盤讀取數(shù)據(jù)。頁面緩存的價值有兩個方面:第一,訪問磁盤的速度遠遠低于訪問內存的速度,因此,從內存訪問數(shù)據(jù)比磁盤訪問更快;第二,數(shù)據(jù)一旦被訪問,就很可能在短期內再次被訪問到。這種在短期內集中訪問同一片數(shù)據(jù)的原理被稱作臨時局部原理(temporal locality)。臨時局部原理能保證,如果在第一次訪問數(shù)據(jù)時緩存它,那就極有可能在短期內再次被高速緩存命中。

        數(shù)據(jù)格式轉化一般由序列化和反序列化[11]過程組成。將程序運行過程中的對象轉化成可以存儲或運輸?shù)男问降倪^程,就是序列化(serialization)。反之,序列化結果轉化成對象形式的過程,就是反序列化(de-serialization)。在傳統(tǒng)的關系型數(shù)據(jù)庫中,序列化和反序列化操作都隱含在數(shù)據(jù)庫讀寫操作當中,對用戶是透明的。內存數(shù)據(jù)庫和嵌入式數(shù)據(jù)庫的序列化和反序列化過程一般需要用戶自定義[12]。由于各個系統(tǒng)的軟硬件規(guī)格不同,一般需要編程語言無關的格式來序列化數(shù)據(jù),常見的有xml/json[13]等可見字符文本,以及效率更高的二進制數(shù)據(jù)流傳輸方式protocol buffers[14]。當數(shù)據(jù)量很大,或者獲取頻次很高時,序列化和反序列化會大量消耗系統(tǒng)資源。

        2 基于內存映射文件的快速讀取方法

        針對上述提出的內核態(tài)到用戶態(tài)的內存拷貝,以及反序列化等帶來的讀取性能問題,文中針對性地提出改進方法。

        2.1 減少內存拷貝

        為了盡可能地減少拷貝操作,降低內存消耗,可采用系統(tǒng)調用mmap,即內存映射技術。內存映射技術是Linux的一種內存管理方法,通過這種方法,在不占用額外的內存空間條件下,就能實現(xiàn)目標磁盤文件與進程用戶態(tài)虛擬內存空間的對應關系,省去了文件IO等操作。

        圖2 內核態(tài)與用戶態(tài)的內存拷貝與映射

        以讀取性能較優(yōu)的嵌入式數(shù)據(jù)庫Berkeley DB為例,比較分析mmap的性能優(yōu)勢。Berkeley DB以文件的形式存儲數(shù)據(jù),讀取數(shù)據(jù)所采用的系統(tǒng)調用是read。read和mmap方式的差異比較如圖2所示。磁盤文件裝載于內核態(tài)的頁面緩存區(qū)域,進程以read方式訪問文件,在其用戶態(tài)地址空間獨立拷貝一份數(shù)據(jù),每個read進程獨享一份數(shù)據(jù)拷貝。也可以在多個read進程間共享一份用戶態(tài)數(shù)據(jù)拷貝,其弊端是為了保證數(shù)據(jù)一致性需要額外的鎖機制,讀取頻繁時多個進程競爭等待造成讀取效率降低,由于此問題較復雜且與該文相關度不高,不再詳述。相對而言,mmap方式既簡單又高效,不但沒有拷貝操作,內存消耗也很低,整個物理內存只存在一份文件數(shù)據(jù)(在頁面緩存區(qū)域)。應用程序不需要考慮文件映射內的數(shù)據(jù)是否已經(jīng)裝載,也不需要考慮如何在多個進程間共享,這些Linux內核都已處理,對用戶透明。如果磁盤文件過大超過了物理內存大小,Linux內核會以LRU(least recent used)算法把冷數(shù)據(jù)置換出來,從而釋放內存來存儲新數(shù)據(jù),最終在頁面緩存中的數(shù)據(jù)是經(jīng)常被訪問的熱數(shù)據(jù)。

        2.2 優(yōu)化數(shù)據(jù)格式

        復雜對象不但數(shù)據(jù)量大,且數(shù)據(jù)間關系復雜,體現(xiàn)在數(shù)據(jù)結構上就是指針引用較多。當把復雜對象序列化于文件時,指針就失效了,必須將相應的指針轉化為指針指向的目標數(shù)據(jù)塊在文件中的偏移量。如圖3所示的哈希表,哈希桶內的指針指向鍵值對結構,當序列化于文件時,該指針需修改為鍵值對結構在文件中的偏移量。當用戶進程讀取該哈希表時,得到的文件偏移量加上文件映射首地址,即是目標鍵值對結構的內存地址。

        圖3 復雜對象的指針轉化

        在64位地址空間[15]當中,有大量的空閑空間可供程序使用。因此,經(jīng)過如下步驟(見圖4),則可在文件中直接存儲指針,避免文件偏移量的轉化:

        (1)序列化進程在指定虛擬內存區(qū)域內分配對象內存,直至整個復雜對象存儲于該指定虛擬內存區(qū)域。

        (2)把該內存區(qū)域內的二進制數(shù)據(jù)dump到內存鏡像文件。

        (3)由反序列化進程映射該內存鏡像文件,映射地址為之前指定的虛擬內存區(qū)域。

        (4)復雜對象不需要任何格式轉化,即可被反序列化進程使用。

        圖4 復雜對象共享過程

        2.3 復用模板庫和容器

        如2.2節(jié)所述,優(yōu)化數(shù)據(jù)格式的重點在于如何把一個復雜對象序列化于指定虛擬內存區(qū)域。假設某個復雜對象為多重key-value結構(value部分又是一個key-value結構),這就要求開發(fā)人員開發(fā)一個特定的哈希表數(shù)據(jù)結構。當復雜對象使用的數(shù)據(jù)結構更多時,相應的特定數(shù)據(jù)結構開發(fā)工作也更多,開發(fā)效率低下。由此,引入了可復用組件C++標準模板庫[16]。

        C++標準模板庫STL(standard template library)是一套標準化組件,由六大組件組成:

        (1)container:泛型容器,基本數(shù)據(jù)結構有數(shù)組vector,鏈表list,二叉樹map,哈希表unordered_map等。

        (2)algorithms:泛型算法,常見的排序sort,搜索search等。

        (3)iterator:迭代器,借此container和algorithms解耦,兩者可以各自獨立發(fā)展互不關聯(lián)。

        (4)function object:是一種模板函數(shù)對象,常見的有map容器中的比較對象std∷less。

        (5)adaptor:適配器,修飾container或function object接口的一種組件。比如棧stack作為容器適配器,可以實現(xiàn)為基礎容器類型(vector,list)的適配。

        (6)allocator:內存分配器,STL提供了默認內存分配器。

        泛型容器提供了一些常用的數(shù)據(jù)結構,可以嵌套使用,比如借助unordered_map可實現(xiàn)多重key-value結構。內存分配器負責數(shù)據(jù)對象的內存分配,默認內存分配器是基于gnu libc的內存分配算法[17],內存分配分散于進程堆空間之中,無法區(qū)分共享數(shù)據(jù)與私有數(shù)據(jù),兩類數(shù)據(jù)交錯存放。通過自定義內存分配器,使得需要共享的大小不一的各種C++對象從指定的地址空間中分配,其他私有對象仍然從進程堆空間分配。最終,序列化進程把指定內存區(qū)域內的連續(xù)內存塊數(shù)據(jù)dump出來保存,即為可共享的數(shù)據(jù)文件。

        3 系統(tǒng)關鍵實現(xiàn)與對比驗證

        該方案的實現(xiàn)關鍵點在于如何把對象序列化于數(shù)據(jù)文件當中。數(shù)據(jù)的讀取操作相對簡單,把文件映射獲得的內存區(qū)域首地址指針強制轉化為C++對象指針類型即可。

        3.1 創(chuàng)建空洞文件

        初始階段創(chuàng)建空文件用以存放目標復雜對象。由于對象長度大小事先無法確定,因此一般做法是創(chuàng)建一個較小的空文件,隨著復雜對象的擴張而不斷延長文件長度。這個辦法的缺點是實現(xiàn)相對復雜,延長操作過多的話會影響寫入性能。

        借助空洞文件,可以解決該問題。在Linux文件操作中,文件位移量是可以大于文件的當前長度的,在這種情況下,對該文件的下一次寫將延長該文件,并在文件中構成一個空洞,即為空洞文件。位于文件中但沒有寫過的字節(jié)都被預設為0。空洞是否占用硬盤空間由文件系統(tǒng)決定,在一般文件系統(tǒng)中不占用硬盤空間,意味著不需要大量的寫0操作,創(chuàng)建過程耗時極短。

        在寫C++對象數(shù)據(jù)文件前,先創(chuàng)建一個空洞文件,文件長度為預估數(shù)據(jù)量的若干倍,比如10倍。無需擔心浪費磁盤空間,因為最終序列化完畢時,可以根據(jù)實際數(shù)據(jù)量縮減文件長度。

        3.2 基于內存映射技術的內存分配器

        內存分配器是處理應用對于內存的分配和釋放要求的,默認內存分配器所分配內存處于進程堆空間。該方案自定義的基于內存映射技術的內存分配器,可分配內存來至磁盤文件映射出的連續(xù)內存空間。其主要接口和成員變量如下:

        class MemoryMapAllocator

        {

        public:

        MemoryMapAllocator(const char* filePath, unsigned long maxSize, void* address);

        ~MemoryMapAllocator();

        void* allocate(unsigned long size);

        void release(const void* ptr);

        private:

        void* m_currentPointer;

        };

        構造函數(shù)的作用是根據(jù)數(shù)據(jù)文件目錄位置,以及預估的數(shù)據(jù)最大大小,創(chuàng)建空洞文件,并映射入指定的用戶態(tài)地址空間(函數(shù)參數(shù)address),成員變量m_currentPointer初始化為映射空間的首地址。

        析構函數(shù)的主要功能是以msync系統(tǒng)函數(shù)同步數(shù)據(jù)寫入磁盤,再以munmap系統(tǒng)函數(shù)撤銷內存映射,即數(shù)據(jù)持久化過程。

        成員函數(shù)allocate是內存分配操作方法,首先m_currentPointer指針自增函數(shù)輸入?yún)?shù)size字符數(shù),然后函數(shù)返回自增前m_currentPointer的值。一般為了提升內存訪問效率,對輸入?yún)?shù)size做對齊工作,向上取整8的倍數(shù)(64位操作系統(tǒng)環(huán)境)。

        成員函數(shù)release是釋放內存操作方法,在方案中并不必要。所有C++對象都分配于映射地址空間,所有數(shù)據(jù)寫入之后,撤銷文件映射并把內存數(shù)據(jù)同步于磁盤文件,所有對象內存自然釋放,因此release函數(shù)內部實現(xiàn)可以為空操作。一種更復雜的實現(xiàn)是重復利用釋放的內存,借助精細的內存管理機制(如slab算法[18]),記錄所有釋放的內存,內存分配算法優(yōu)先在其中尋找符合大小要求的閑置空間。實際應用當中,此類釋放內存數(shù)量有限,重復利用價值不高,且代碼復雜度高,可維護性差,不建議使用。

        3.3 多線程支持

        在創(chuàng)建數(shù)據(jù)文件時,如果數(shù)據(jù)量很大,可借助多線程并發(fā)處理能力來加速處理。為此內存分配器需設計成線程安全。

        最簡單的方法是在類MemoryMapAllocator中新增鎖對象,每次調用allocate方法時加鎖,函數(shù)返回時釋放鎖,保證只有一個線程在修改m_currentPointer指針,其余試圖申請內存的線程處睡眠等待狀態(tài)。當線程爭搶鎖劇烈時,頻繁的線程切換就會成為性能瓶頸。

        為了解決鎖帶來的弊端,可采用原子操作[19]。所謂的原子操作是指不會被線程調度機制打斷的操作,一旦操作開始,就一直運行到結束,中間不會被其他線程操作打斷。其實現(xiàn)原理是依靠硬件的支持,在X86平臺上,CPU提供了在指令執(zhí)行期間對總線加鎖的手段。避免了線程切換,提升處理速度。

        GCC編譯器當前已經(jīng)支持了原子操作,可以對1、2、4、8字節(jié)的數(shù)值或指針類型進行原子的加、減、與、或、異等操作。對于m_currentPointer的加法操作,可以靠原子操作函數(shù)__sync_fetch_and_add(type *ptr, type value)完成,其實現(xiàn)細節(jié)是將value加到*ptr,結果更新到*ptr,并返回操作之前*ptr的值。

        3.4 讀取效率對比

        為了對改進復雜對象讀取性能做進一步的分析,對傳統(tǒng)內存數(shù)據(jù)庫redis、嵌入式數(shù)據(jù)庫berkeley DB和基于內存映射文件的復雜對象讀取方法進行了性能對比測試。測試目的是在讀取相同數(shù)據(jù)量的前提下,比較各個方案的響應時間值。軟件配置為Linux內核2.6.32,redis libhiredis 0.13,berkeley DB libdb_cxx 4.7;硬件配置CPU頻率2.60 GHz,內存256 G。

        在以上測試環(huán)境中,創(chuàng)建一個進程順序進行三次不同方案的數(shù)據(jù)讀取操作,保證了軟硬件資源一致。其中內存數(shù)據(jù)庫redis服務端與客戶端部署于同一臺服務器,避免網(wǎng)絡延時帶來的誤差。內存映射文件數(shù)據(jù)庫采用了C++標準模板庫容器unordered_map。

        三個數(shù)據(jù)庫存儲相同key-value鍵值對1 024個,每個key平均2.9 Bytes,每個value平均2 986 Bytes,讀取程序設計為遍歷讀取這1 024個key共600遍,即614 400次查詢操作,實驗結果見表1。

        表1 三種數(shù)據(jù)庫方案讀取性能測試結果

        從結果上看,文中提出方法的讀取性能相對于傳統(tǒng)方案有非常顯著的提升,與性能較優(yōu)的嵌入式數(shù)據(jù)庫相比其讀取響應時間提升10倍以上。而且如前所述,內存數(shù)據(jù)庫與嵌入式數(shù)據(jù)庫的內存消耗量與讀取進程個數(shù)成線性增長,因為每個進程都要拷貝存儲數(shù)據(jù),而內存映射文件數(shù)據(jù)庫不需要拷貝,其內存消耗量與讀取進程個數(shù)基本不相關。

        該方案的另一個優(yōu)點在于支持各種復雜對象,而不單限于key-value結構。由于內存數(shù)據(jù)庫、嵌入式數(shù)據(jù)庫支持的結構類型有限,故只比對了key-value結構。如果把一個復雜對象分拆成多個key-value鍵值對存儲于普通數(shù)據(jù)庫中,其性能更無法與面向對象的內存映射文件數(shù)據(jù)庫相提并論。原因是前者需要多次索引搜索才能組裝成完整的復雜對象,而后者沒有這個過程,所有的對象內數(shù)據(jù)關系都已經(jīng)通過指針關聯(lián)。

        4 結束語

        傳統(tǒng)數(shù)據(jù)庫在高并發(fā)應用場景中,數(shù)據(jù)拷貝操作頻繁,數(shù)據(jù)量較大時容易成為性能瓶頸。當數(shù)據(jù)對象結構復雜時,不但數(shù)據(jù)庫表結構、索引設計復雜,而且序列化與反序列化過程耗時嚴重。該方案通過內存映射文件、自定義內存分配器、標準模板庫容器等技術,有效解決了復雜對象讀取性能問題。讀取過程沒有進程間通信,不需要數(shù)據(jù)拷貝,不需要反序列化過程即可直接引用對象,與傳統(tǒng)數(shù)據(jù)庫讀取效率對比的實驗表明性能可提升10倍以上。同時,還具有底層技術成熟穩(wěn)定、開發(fā)代碼量少、易于維護等優(yōu)點。內存映射文件技術得到了廣泛的支持,Linux等類Unix操作系統(tǒng)中都提供了相關系統(tǒng)調用。標準模板庫提供了諸多常用數(shù)據(jù)結構,大大降低了復雜對象結構設計與開發(fā)成本。借由此類成熟技術,開發(fā)過程周期短,易于實現(xiàn),后期維護更新成本低,在實際應用中運行穩(wěn)定。在數(shù)據(jù)庫災備設計方面,由于數(shù)據(jù)存儲于文件,易于傳輸,如果數(shù)據(jù)丟失,可以很快從災備數(shù)據(jù)文件中恢復。因此,該方案實用性高,適用于數(shù)據(jù)訪問方式寫少讀多的高并發(fā)高性能搜索、計算等后臺服務系統(tǒng),在工程實踐中有重要的典型意義。

        猜你喜歡
        進程嵌入式數(shù)據(jù)庫
        債券市場對外開放的進程與展望
        中國外匯(2019年20期)2019-11-25 09:54:58
        搭建基于Qt的嵌入式開發(fā)平臺
        數(shù)據(jù)庫
        財經(jīng)(2017年2期)2017-03-10 14:35:35
        嵌入式軟PLC在電鍍生產流程控制系統(tǒng)中的應用
        數(shù)據(jù)庫
        財經(jīng)(2016年15期)2016-06-03 07:38:02
        數(shù)據(jù)庫
        財經(jīng)(2016年3期)2016-03-07 07:44:46
        數(shù)據(jù)庫
        財經(jīng)(2016年6期)2016-02-24 07:41:51
        Altera加入嵌入式視覺聯(lián)盟
        倍福 CX8091嵌入式控制器
        自動化博覽(2014年4期)2014-02-28 22:31:15
        社會進程中的新聞學探尋
        民主與科學(2014年3期)2014-02-28 11:23:03
        亚洲婷婷丁香激情| 音影先锋中文字幕在线| 亚洲日韩精品无码专区网址| 久久精品人人做人人爽| 免费国产黄线在线播放| 丝袜美腿诱惑一二三区| 亚洲精品午夜久久久九九| 熟妇激情内射com| 婷婷丁香五月亚洲| 精品一区二区三区女同免费| 日韩精品免费一区二区三区观看| 中文人妻熟妇乱又伦精品| 丝袜AV在线一区二区三区| 国产综合一区二区三区av| 成人久久久精品乱码一区二区三区| 国产啪亚洲国产精品无码| 在线视频一区色| 中文字幕日韩人妻在线| 日韩亚洲一区二区三区四区 | 性欧美老人牲交xxxxx视频| 精品手机在线视频| 91精品国产色综合久久不| 91丝袜美腿亚洲一区二区| 国产一区二区精品久久| 亚洲欧美日韩国产精品一区| 丰满少妇av一区二区三区| 四虎国产成人永久精品免费| 天天躁日日躁狠狠躁av中文| 亚洲成AV人国产毛片| 日本精品免费看99久久| 久久9精品区-无套内射无码| 一级呦女专区毛片| 日韩激情av不卡在线| 少妇高潮惨叫久久久久电影69| 成人无码一区二区三区网站| 青榴社区国产精品| 中文字幕影片免费人妻少妇| 无码人妻久久一区二区三区免费| 婷婷亚洲国产成人精品性色| 亚洲国产一区二区,毛片| 初尝人妻少妇中文字幕|