NoSQL資料庫Redis幾個認識誤區

2021-05-24 09:11:07 字數 2893 閱讀 2750

前幾天微博發生了一起大的系統故障

, 很多技術的朋友都比較關心,其中的原因不會超出james hamilton在on designing and deploying internet-scale service(1)概括的那幾個範圍,james第一條經驗「design for failure」是所有網際網路架構成功的乙個關鍵。網際網路系統的工程理論其實非常簡單,james *****中內容幾乎稱不上理論,而是多條實踐經驗分享,每個公司對這些經驗的理解及執行力決定了架構成敗。

題外話說完,最近又研究了redis

。去年曾做過乙個memcachedb, tokyo tyrant, redis performance test這個問題的結果影響了我們怎麼用redis。如果你認為redis是乙個key value store, 那可能會用它來代替mysql;如果認為它是乙個可以持久化的cache, 可能只是它儲存一些頻繁訪問的臨時資料。redis是remote dictionary server的縮寫,在redis在官方**的的副標題是a persistent key-value database with built-in net inte***ce written in ansi-c for posix systems,這個定義偏向key value store。還有一些看法則認為redis是乙個memory database,因為它的高效能都是基於記憶體操作的基礎。另外一些人則認為redis是乙個data structure server,因為redis支援複雜的資料特性,比如list, set等。對redis的作用的不同解讀決定了你對redis的使用方式。

網際網路資料目前基本使用兩種方式來儲存,關聯式資料庫或者key value。但是這些網際網路業務本身並不屬於這兩種資料型別,比如使用者在社會化平台中的關係,它是乙個list,如果要用關聯式資料庫儲存就需要轉換成一種 多行記錄的形式,這種形式存在很多冗餘資料,每一行需要儲存一些重複資訊。如果用key value儲存則修改和刪除比較麻煩,需要將全部資料讀出再寫入。redis在記憶體中設計了各種資料型別,讓業務能夠高速原子的訪問這些資料結構,並且不 需要關心持久儲存的問題,從架構上解決了前面兩種儲存需要走一些彎路的問題。

很多開發者都認為redis不可能比memcached快,memcached完全基於記憶體,而redis具有持久化儲存特性,即使是非同步 的,redis也不可能比memcached快。但是測試結果基本是redis佔絕對優勢。一直在思考這個原因,目前想到的原因有這幾方面。

redis的資料全部放在記憶體帶來了高速的效能,但是也帶來一些不合理之處。比如乙個中型**有100萬註冊使用者,如果這些資料要用redis來存 儲,記憶體的容量必須能夠容納這100萬使用者。但是業務實際情況是100萬使用者只有5萬活躍使用者,1周來訪問過1次的也只有15萬使用者,因此全部100萬用 戶的資料都放在記憶體有不合理之處,ram需要為冷資料買單。

這跟作業系統非常相似,作業系統所有應用訪問的資料都在記憶體,但是如果物理記憶體容納不下新的資料,作業系統會智慧型將部分長期沒有訪問的資料交換到磁碟,為新的應用留出空間。現代作業系統給應用提供的並不是物理記憶體,而是虛擬記憶體(virtual memory)的概念。

基於相同的考慮,redis 2.0也增加了vm特性。讓redis資料容量突破了物理記憶體的限制。並實現了資料冷熱分離。

redis的vm依照之前的epoll實現思路依舊是自己實現。但是在前面作業系統的介紹提到os也可以自動幫程式實現冷熱資料分離,redis只 需要os申請一塊大記憶體,os會自動將熱資料放入物理記憶體,冷資料交換到硬碟,另外乙個知名的「理解了現代作業系統(3)」的varnish就是這樣實 現,也取得了非常成功的效果。

作者antirez在解釋為什麼要自己實現vm中提到幾個原因(6)。主要os的vm換入換出是基於page概念,比如os vm1個page是4k, 4k中只要還有乙個元素即使只有1個位元組被訪問,這個頁也不會被swap, 換入也同樣道理,讀到乙個位元組可能會換入4k無用的記憶體。而redis自己實現則可以達到控制換入的粒度。另外訪問作業系統swap記憶體區域時block 程序,也是導致redis要自己實現vm原因之一。

作為乙個key value存在,很多開發者自然的使用set/get方式來使用redis,實際上這並不是最優化的使用方法。尤其在未啟用vm情況下,redis全部資料需要放入記憶體,節約記憶體尤其重要。

假如乙個key-value單元需要最小占用512位元組,即使只存乙個位元組也佔了512位元組。這時候就有乙個設計模式,可以把key復用,幾個key-value放入乙個key中,value再作為乙個set存入,這樣同樣512位元組就會存放10-100倍的容量。

這就是為了節約記憶體,建議使用hashset而不是set/get的方式來使用redis,詳細方法見參考文獻(7)。

其實aof目的主要是資料可靠性及高可用性,在redis中有另外一種方法來達到目的:replication。由於redis的高效能,複製基本沒有延遲。這樣達到了防止單點故障及實現了高可用。

要想成功使用一種產品,我們需要深入了解它的特性。redis效能突出,如果能夠熟練的駕馭,對國內很多大型應用具有很大幫助。希望更多同行加入到redis使用及**研究行列。

參考文獻

on designing and deploying internet-scale service(pdf)

facebook』s new real-time messaging system: hbase to store 135+ billion messages a month

what』s wrong with 1975 programming

linux epoll is now supported

(google groups)

cas and why i don』t want to add it to redis

(google groups)

plans for virtual memory

(google groups)

full of keys

(salvatore antirez sanfilippo)

-eof-

NoSQL資料庫之 Redis

redis是基於記憶體的nosql資料庫。前身是memcached,但是memcached不支援持久化,沒有豐富的資料型別。redis存放的資料是key values鍵值對。1 解壓 tar zxvf redis 3.0.5.tar.gz 預編譯,需要gcc環境。apt get install gc...

NoSql資料庫之redis資料庫簡介及安裝

一 redis資料庫簡介 redis是用c語言開發的乙個開源的高效能鍵值對 key value 資料庫。它通過提供多種鍵值資料型別來適應不同場景下的儲存需求,目前為止redis支援的鍵值資料型別如 下 1 字串型別 string 2 雜湊型別 hash 3 列表型別 list 4 集合型別 set ...

Nosql資料庫 redis(四)資料型別

上篇部落格介紹了兩種資料型別string和hash,下面我們接著來看 redis 是乙個鍊錶結構,主要的功能是push pop 獲取乙個範圍的所有值等等,操作中key理解為鍊錶的名字。redis的list型別其實就是乙個每個子元素都是string型別的雙向鍊錶。我們可以通過push pop操作從鍊錶...