Redis數據庫特性分析
學術研究
作者:馬豫星
摘 要:Redis是一款開源的、網絡化的、基於內存的、可進行數據持久化的Key-Value存儲係統。詳細介紹了redis數據庫底層數據結構、數據庫的持久化方式、數據庫事務特性以及隱藏在設計之中的一些考量。闡明了Redis高效性的原因在於其精簡高效的底層數據結構設計以及對具有高消耗的功能進行分散處理。
關鍵詞:數據庫;Redis;NoSQL;分散處理
中圖分類號:TP316 文獻標識碼:A 文章編號:2095-1302(2015)03-00-02
0 引 言
隨著互聯網的發展以及Web 2.0的興起,超大規模以及高並發的純動態型網站日漸成為主流,由於SNS類網站在數據存取過程中有著實時性等剛性需求的原因,致使關係型數據庫越來越不足以勝任,這使得目前NoSQL數據庫慢慢成了人們所關注的焦點,並大有成為取代關係型數據庫而成為未來主流數據存儲模式的趨勢。當前NoSQL數據庫很多,大部分都是開源的,其中比較知名的有:MemcacheDB、Redis、Tokyo Cabinet、Flare、MongoDB、CouchDB、Cassandra、Voldemort等。本文主要介紹Redis,這是一款足以滿足海量讀寫需求基於Key-Value數據存儲方式的高性能NoSQL數據庫。
1 Redis簡介
Redis是一款開源的、網絡化的、基於內存的、可進行數據持久化的Key-Value存儲係統。它的數據模型建立在外層,類似於其它結構化存儲係統,是通過Key映射Value的方式來建立字典以保存數據,有別於其它結構化存儲係統的是,它支持多類型存儲,包括String、List、Set、Sort set和Hash等,你可以在這些數據類型上做很多原子性操作。
在操作方麵,Redis基於TCP協議的特性使得它可以通過管道的方式進行數據操作,Redis本身提供了一個可連接Server的客戶端,通過客戶端,可方便地進行數據存取操作。
2 Redis底層數據結構中的兩種:字符串和字典
在Redis的內部, 數據結構類型值由高效的數據結構和算法進行支持, 並且在Redis 自身的構建當中,也大量用到了這些數據結構。
2.1 字符串
SDS(Simple Dynamic String,簡單動態字符串)是Redis底層所使用的字符串表示,幾乎所有的Redis模塊中都用了SDS。用SDS取代C默認的char*類型。
因為char*類型的功能單一,抽象層次低,並且不能高效地支持一些Redis常用的操作,所以在Redis程序內部,絕大部分情況下都會使用SDS而不是char*來表示字符串。
在C語言中,字符串可以用一個\0結尾的char數組來表示。但是,它並不能高效地支持長度計算和追加這兩種操作:
(1)計算字符串長度的複雜度為θ(N)。
(2)對字符串進行N次追加,必定需要對字符串進行N次內存重分配。
在Redis內部,字符串的追加和長度計算很常見,這兩個簡單的操作不應該成為性能的瓶頸。
另外,Redis除了處理C字符串之外,還需要處理單純的字節數組,以及服務器協議等內容,所以為了方便起見,Redis的字符串表示還應該是二進製安全的:程序不應對字符串裏麵保存的數據做任何假設,數據可以是以\0結尾的C字符串,也可以是單純的字節數組,或者其他格式的數據。
考慮到這兩個原因,Redis使用SDS類型替換了C語言的默認字符串表示:SDS既可高效地實現追加和長度計算,同時是二進製安全的。
值得一提的是,在Redis最初的設計中就加入了統計信息:
在設計SDS的時候,在內部使用了zmalloc與zfree來動態使用內存,並記錄占有內存大小,方便計算Redis的性能。
2.2 字典
實現字典的方法有很多種:為了兼顧高效和簡單性,Redis使用了哈希表。在實現哈希表時,有一個問題就是采用何種策略來解決碰撞問題。對於使用鏈地址法來解決碰撞問題的哈希表來說,哈希表的性能取決於哈希表大小與保存節點數量之間的比率:
(1)哈希表的大小與節點數量,比率在1:1時,哈希表的性能最好;
(2)如果節點數量比哈希表的大小要大很多的話,那麼哈希表就會退化成多個鏈表,哈希表本身的性能優勢便不複存在;