網上有一篇介紹Redis的文章,由淺入深地講解了Redis:http://blog.mjrusso.com/2010/10/17/redis-from-the-ground-up.html。強烈建議對Redis有興趣或需要使用的朋友閱讀這篇文章。
提到Redis,第一反應就是記憶體k/v緩衝,並且很多人會拿它與Memcached相比較,畢竟他們都是以記憶體作為儲存介質的。 如果簡單地比較Redis與Memcached的區別,大多數都會得到以下觀點:
1 Redis不僅僅支援簡單的k/v類型的資料,同時還提供list,set,hash等資料結構的儲存。
2 Redis支援資料的備份,即master-slave模式的資料備份。
3 Redis支援資料的持久化,可以將記憶體中的資料保持在磁碟中,重啟的時候可以再次載入進行使用。
拋開這些,可以深入到Redis內部構造去觀察更加本質的區別,理解Redis的設計。我覺得最值得參考的就是Redis的記憶體模型設計。推薦參考這兩篇文章:Redis Virtual Memory: the Story and the Code和Redis Virtual Memory subsystem。
在Redis中,並不是所有的資料都一直儲存在記憶體中的。這是和Memcached相比一個最大的區別(我個人是這麼認為的)。Redis只會緩衝所有的key的資訊,如果Redis發現記憶體的使用量超過了某一個閥值,將觸發swap的操作,Redis根據“swappability = age*log(size_in_memory)”計算出哪些key對應的value需要swap到磁碟。然後再將這些key對應的value持久化到磁碟中,同時在記憶體中清除。這種特性使得Redis可以保持超過其機器本身記憶體大小的資料。當然,機器本身的記憶體必須要能夠保持所有的key,畢竟這些資料是不會進行swap操作的。同時由於Redis將記憶體中的資料swap到磁碟中的時候,提供服務的主線程和進行swap操作的子線程會共用這部分記憶體,所以如果更新需要swap的資料,Redis將阻塞這個操作,直到子線程完成swap操作後才可以進行修改。
可以參考使用Redis特有記憶體模型前後的情況對比:
VM off: 300k keys, 4096 bytes values: 1.3G used
VM on: 300k keys, 4096 bytes values: 73M used
VM off: 1 million keys, 256 bytes values: 430.12M used
VM on: 1 million keys, 256 bytes values: 160.09M used
VM on: 1 million keys, values as large as you want, still: 160.09M used
當從Redis中讀取資料的時候,如果讀取的key對應的value不在記憶體中,那麼Redis就需要從swap檔案中載入相應資料,然後再返回給請求方。這裡就存在一個I/O線程池的問題。在預設的情況下,Redis會出現阻塞,即完成所有的swap檔案載入後才會相應。這種策略在用戶端的數量較小,進行大量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程式程式中,這顯然是無法滿足大並發的情況的。所以Redis運行我們設定I/O線程池的大小,對需要從swap檔案中載入相應資料的讀取請求進行並行作業,減少阻塞的時間。
如果希望在海量資料的環境中使用好Redis,我相信理解Redis的記憶體設計和阻塞的情況是不可缺少的
更多關於NoSQL的文章可以參考:http://www.cnblogs.com/gpcuster/tag/NoSQL/