《Redis官方文件》 FAQ
原文地址 譯者:zivyu
為什麼Redis與其他的k-v儲存相比不一樣
有兩個主要的原因
- redis在鍵-值資料庫中是一個不同的發展方向,值可以包含更復雜的資料型別,同時許多原子操作定義在這些資料型別上。redis的資料型別和基本資料結構密切相關,沒有額外的抽象層,同樣對於程式設計師也是直接可見的。
- redis是一個在記憶體中但是可以持久化到磁碟上的資料庫,所以它代表了一個不同的權衡,高速讀寫被實現,但是對資料集有限制,那就是不能大於記憶體的大小。在記憶體中的資料庫還有另外的優點,記憶體中表示的複雜資料結構比一些在磁碟中的資料結構更容易操作,所以redis可以做很多操作而內部並不複雜。同時,兩種磁碟儲存格式(RDB和AOF)也不需要適合於隨機儲存。所以,資料是緊湊的,而且總是在末尾新增生成。
Redis的記憶體佔用
下面給出一些例子:
- 一個空的例項~1MB
- 一百萬個小的字串key->value ~100MB
- 一百萬個雜湊key->value,表示一個有五個欄位的物件 ~ 200MB
測試你的用例是很簡單的。使用redis-benchmark工具生成隨機資料,然後使用Info memory檢查空間使用。
當儲存一些相同的key的時候,64位系統將比32位系統使用更多的記憶體,除非key和value很小。這是因為在64位系統使用8個位元組的指標。當然,64位系統的優點是你可以擁有更多的記憶體,所以為了執行大型的redis服務,一個64位系統或多或少是需要的。還有一種選擇是分片。
我喜歡redis的高階操作和特性,但是我不喜歡它在記憶體中做了所有的事情,並且我不能擁有比記憶體更大的資料集。怎麼計劃改變這點?
在過去,redis開發者嘗試用虛擬記憶體和別的系統,為了允許比記憶體更大的資料集的使用。但是最終我們很樂意只做好一件事:記憶體用來資料服務,磁碟用來資料儲存。所以現在還沒有計劃來建立一個對於redis的磁碟上的後端。畢竟,redis是它當前設計的直接結果。
你真正的問題不是總共的記憶體需要,事實上你需要把你的資料切分到多個redis例項中。,請閱讀Partitioning page獲取更多資訊。
Redis和一個磁碟上的資料庫一起使用是個好主意嗎?
是的,一個通常的設計模式是把寫非常密集的小資料放在redis中,大的二進位制資料塊放在SQL資料庫或在磁碟資料庫中保持最終一致。
我是否可以做些事情來降低Redis的記憶體使用?
如果可以的話,使用32位的Redis 例項。同樣,使用小的雜湊、列表、有序集和整數集也是很好的,因為Redis能夠在一些元素的特殊情況下表示那些資料型別,以一種更加緊湊的方式。更多的資訊請參考Memory Optimization page。
如果Redis執行時記憶體不足會發生什麼?
Redis要麼被Linux kill,一個錯誤導致崩潰,要麼就開始慢下來。現代作業系統的malloc()函式返回null是不常見的,通常服務開始調換,redis的效能開始降級,所以你可能會注意到有一些錯誤的事情。
INFO指令可以 報告redis正在使用的記憶體大小,所以你可以寫個指令碼通過檢查一些臨界條件來監視你的redis服務。
Redis有一個保護措施允許使用者設定一個記憶體使用的最大限度,在配置檔案裡使用maxmemory選項來設定一個Redis可以使用的記憶體限制。如果限制達到,redis將回複寫命令一個錯誤(但是仍然可以繼續接受只讀命令),或者當你使用redis作為快取的情況下,當最大記憶體限制達到的時候,你可以配置redis來丟棄某些key值。
在Linux下後臺儲存失敗且有一個fork()錯誤,雖然我有許多空閒記憶體
簡短的回答:echo 1 > /proc/sys/vm/overcommit_memory
下面開始更長的答案:
Redis在後臺的儲存機制依賴於作業系統中fork的copy-on-write:也就是redis fork(建立一個子程序)是父程序的一個完整精確拷貝。子程序轉儲到磁碟上的資料庫然後退出。理論上來說,子程序作為一個副本應該使用和父親一樣多的記憶體,但是實際上由於大部分現代作業系統的copy-on-write的實現,父程序和子程序將共享記憶體頁。當他被父程序或者子程序改變的時候,一個記憶體頁將被複制。因此,從理論上講,當子程序儲存的時候,所有記憶體頁可能被改變,Linux不能提前告訴子程序多少記憶體被使用,所以如果overcommit_memory設定被設定為0,建立將會失敗,除非有同樣多的空閒記憶體。結果是,如果你有3GB的redis資料並且只有2GB的空閒記憶體,它將會失敗。
把overcommit_memory設定為1來告訴Linux以更加樂觀的方式來執行fork操作,並且這確實是你想要的。
Redis的磁碟快照是原子的嗎?
是的,redis的後臺儲存程序總是被fork當服務沒有執行執行的時候,所以記憶體中每個成為一個原子的指令從檢視磁碟快照來說也是原子的。
Redis是單程序的,我怎麼利用多CPU?
Redis中CPU成為你的瓶頸是非常不可能的,通常redis要麼是記憶體要麼就是網路繫結。例如,在一臺普通的Linux系統上使用流水線redis每秒可以傳輸500k的請求,所以如果你的應用主要使用O(N) 或 O(log(N))的指令,很難使用太多的 CPU。
然而,為了CPU使用率最大化,你可以在同一個機器上啟動多個redis例項,並把它們當作不同的服務對待。在有些時刻,單個機器可能還不夠,所以如果你想使用多個CPU你可以開始思考一些方式去更早的碎片化。
單個redis能持有的key的最大數量是多少?一個雜湊表、列表、集合 、有序集合中元素的最大數量呢?
Redis可以處理2^32個key,在實際的測試中,單個例項至少處理2.5億 個key。
每個雜湊表、列表、集合、有序集合能持有 2^32個元素。
換句話說,你的限制可能就是你係統的可用記憶體。
我的從節點與主節點相比,有不同數量的key。為什麼?
如果你使用有限制時間的key,這是正常的情況。下面是發生了什麼:
- 在從節點第一次同步的時候,主節點生成一個RDB檔案。
- 這個RDB檔案不包括在主節點中已經過期的key。但是這些key仍然在記憶體中。
- 然而這些key仍然在主節點Redis的記憶體中,即使已經過期了。它們被考慮為不存在,但是記憶體不久之後將被回收。然而這些key不是資料集的一部分,在INFO中和使用
DBSIZE指令
被廣告。 - 當從節點讀取主節點生成的RDB檔案,這些key將不會被load。
作為結果,使用者有許多設定了有效期的key在從節點中看著少很多是很常見的,但是在例項中並沒有什麼實際的影響。
Redis的真正意思?
它的意思是REmote DIctionary Server。
為什麼要開始Redis專案?
最初,redis為了衡量LLOOGG。但是當我完成基本的服務工作,我有了一個把它分享給其他人的想法,然後redis就變成了一個開源的專案。