1. 程式人生 > >非關系型數據庫(NOSQL)-Redis

非關系型數據庫(NOSQL)-Redis

進行 意大利 緩存一致性 主從同步 c/c++ redis 散列 rem 完全

整理一波Redis

簡介,與memcached比較

  官網:http://redis.io

Redis是一個key-value存儲系統。Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)list(鏈表)set(集合)zset(sorted set --有序集合)hash(哈希類型)。

  這些數據類型都支持push/popadd/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。

  在此基礎上,redis支持各種不同方式的排序。

  與memcached一樣,為了保證效率,數據都是緩存在內存中。

區別的是redis

會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。

  Redis 是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部分場合可以對關系數據庫起到很好的補充作用。它提供了JavaC/C++C#PHPJavaScriptPerlObject-CPythonRubyErlang等客戶端,使用很方便。

  Redis支持主從同步。數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹復制

。存盤可以有意無意的對數據進行寫操作。由於完全實現了發布/訂閱機制(觀察者模式)使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主服務器完整的消息發布記錄。同步對讀取操作的可擴展性和數據冗余很有幫助。

  可以充當緩存、隊列等作用。

  源碼脫管: https://github.com/antirez/redis


歷史和發展

  2008年,意大利的一家創業公司Merzia推出一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人Salvatore Sanfilippo便對MySQL的性能感到失望,於是他決定親自為LLOOGG量身定做一個數據庫,並於2009年開發完成,這個數據庫就是

Redis

  不過Salvatore Sanfilippo並不滿足只將Redis用於LLOOGG這一款產品,而是希望更多的人使用它,於是在同一年Salvatore SanfilippoRedis開源發布,並開始和Redis的另一名主要的代碼貢獻者Pieter Noordhuis一起繼續著Redis的開發,直到今天。

短短幾年,Redis就擁有了龐大的用戶群體。Hacker News2012年發布了一份數據庫的使用情況調查,結果顯示有近12%的公司在使用Redis。國內如京東、淘寶、新浪微博、街旁網(已關閉服務器)、知乎網、國外如GitHubStack OverflowFlickr(雅虎旗下圖片分享網站)等都是Redis的用戶。

VMware公司從2010年開始贊助Redis的開發,Salvatore SanfilippoPieter Noordhuis也分別在35月加入VMware,全職開發Redis


特性

1)多種數據類型存儲

  字符串類型 string 512M

  散列類型 hash 2^32-1

  列表類型 list 2^32-1

  集合類型 set 2^32-1

  有序集合類型 zset

2)內存存儲與持久化

  內存的讀寫速度遠快於硬盤

  自身提供了持久化功能(RDB、AOF兩種方式)

3)功能豐富

  可以用作緩存、隊列、消息訂閱/發布

  支持鍵的生存時間

  按照一定規則刪除相應的鍵

4)簡單穩定

  相比SQL而言更加簡潔

  不同語言的客戶端豐富

  基於C語言開發,代碼量只有3萬多行

5)所有操作是原子性的

  Redis 使用單個 Lua 解釋器去運行所有腳本,並且, Redis 也保證腳本會以原子性(atomic)的方式執行: 當某個腳本正在運行的時候,不會有其他腳本或 Redis 命令被執行。 這和使用 MULTI / EXEC 包圍的事務很類似。 在其他別的客戶端看來,腳本的效果(effect)要麽是不可見的(not visible),要麽就是已完成的(already completed)


1.1 Redis持久化的兩種方式

1.1.1 rdbaof比較

rdb

aof

fork一個進程,遍歷hash table,利用copy on write,把整個db dump保存下來。

save, shutdown, slave 命令會觸發這個操作。粒度比較大,如果save, shutdown, slave 之前crash了,則中間的操作沒辦法恢復。

把寫操作指令,持續的寫到一個類似日誌文件裏。(類似於從postgresql等數據庫導出sql一樣,只記錄寫操作)

粒度較小,crash之後,只有crash之前沒有來得及做日誌的操作沒辦法恢復。

註:fork一個進程--

UNIX關於進程管理的一個術語,本質是新開一個進程,但是不從磁盤加載代碼,而是從內存現有進程復制一份。

兩種區別就是,

  一個是持續的用日誌記錄寫操作,crash(崩潰)後利用日誌恢復;

  一個是平時寫操作的時候不觸發寫,只有手動提交save命令,或者是shutdown關閉命令時,才觸發備份操作。

選擇的標準,

  就是看系統是願意犧牲一些性能,換取更高的緩存一致性(aof),

  還是願意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運行save的時候,再做備份(rdb)。rdb這個就更有些 最終一致性(eventually consistent)的意思了。

1.1.2 性能比較

測試方法是用java寫的腳本對redis數據庫進行寫入,看寫入速度。

100000/300000/1000000是數據量,插入的都是string。第一個數據是最小時間,第二個是平均,第三個是數據大小。

100000:

dbmode: 4.8, 5.1, 1477792

aofmode: 9.1, 9.3, 3677803

300000:

dbmode: 16.5, 17.6, 4877792

aofmode: 21.1, 21.4, 11477803

1000000:

dbmode: 61, 65, 16777792

aofmode: 77, 85, 38777849

從簡單分析來看,aofrdb25-80%,但是大規模數據都比較支持慢25%這端。

估計在低數據量下,rdb模式更加占優勢。

數據規模增長時,速率比接近於4:5aof的數據比rdb數據大150%2.5倍上下),這點隨著數據增長基本不變。

從讀性能分析來看,兩者差異不大。同樣,數據分別是最小時間和平均時間。

dbmode: 55, 60

aofmode: 62, 63

差異在10%以內,甚至比最小-平均差異還弱。基本可以視為一致。

非關系型數據庫(NOSQL)-Redis