《Redis官方教程》-FAQ

ali清英發表於2016-04-01

原文連結   譯者:Alexandar Mahone  校對:方騰飛(紅體標記重點)

為什麼Redis不同於其他的鍵值儲存資料庫?

有兩個主要原因:

  • Redis發展方向不同與其他鍵值資料庫,它能包含很多複雜資料型別,對這些資料型別操作都是原子的。Redis資料型別與基本資料結構強相關,直接暴露給程式設計師,沒有增加抽象層。
  • Redis是一個記憶體資料庫,而不是持久化在硬碟資料庫中,因此為了實現高速讀寫,資料集大小不能超過記憶體。記憶體資料庫另一個優點是,記憶體資料庫相對於硬碟資料庫非常容易操作複雜資料結構,因此Redis的可以做很多事情,很少有內部的複雜性。與此同時兩款磁碟儲存格式(RDB和AOF)不需要支援隨機訪問,因此他們是緊湊的,而且總是以追加形式生成(甚至AOF日誌輪換也是一個追加操作,因為新版本是由記憶體中的副本生成)。


Redis記憶體使用情況?

舉幾個例子(所有資料基於64位例項)

  • 一個空例項大約佔用1M記憶體
  • 1百萬簡單字串鍵值對大約佔用100M記憶體
  • 1百萬雜湊表鍵值對,每個物件有5個屬性,大約佔用200M記憶體

為了測試你的用例,使用redis-benchmark工具生成隨機資料集,使用INFO memory命令檢查使用記憶體空間。

儲存相同的鍵,64位系統比32位系統使用更多的記憶體,鍵值很小情況下更明顯。這是因為64位系統指標佔用8位元組。但是64位系統優點是可以配置更多記憶體(校對注:32位作業系統支援的記憶體最多為2的32次方,就是4G),因此為了執行大型Redis伺服器,64位系統或多或少都是需要的。另一種方案是使用分片。


我喜歡Redis的高效能操作和特性,但是不喜歡所有內容都在記憶體中,我不能建立一個比記憶體更大資料集。有計劃改變嗎?

過去為了允許資料集超過RAM大小,Redis開發人員嘗試使用虛擬記憶體和其他系統,但是我們非常高興可以把一件事情做好:資料服務由記憶體提供,磁碟用於儲存資料。所以現在沒有計劃為Redis建立磁碟後端,畢竟Redis大部分特性都是基於其當前架構設計的。

你的真正問題並不是所需的總記憶體,而是你需要劃分你的資料集到多個Redis例項上,為了獲取更多資訊請閱讀本文件中的分割槽頁面


同時使用Redis和磁碟資料庫,是不是一個好想法?

是的,一個通用的設計方案是,在非常頻繁的寫小的資料時採用Redis(並且你需要使用Redis資料結構給你的問題建立高效模型),以及將大資料儲存到SQL資料庫或者最終一致性磁碟資料庫中


有沒有方法降低Redis記憶體使用率?

如果可以的話使用Redis 32位例項。另外,還要善於使用雜湊表,列表,有序集合和整數集,因為在特殊情況下Redis使用這些資料型別可以更緊湊儲存一些元素。可以在記憶體優化頁面獲取更多資訊。


Redis記憶體不足時會發生什麼?

Redis要麼被Linux核心OOM殺掉,丟擲錯誤崩潰,要麼開始變得卡頓。隨著現代作業系統malloc方法通常都不返回NULL,而是伺服器開始交換,因此Redis效能降低,因此你可能會觀察到一些錯誤現象。

INFO命令返回Redis使用記憶體總量,因此你可以編寫指令碼監控Redis伺服器記憶體臨界值。

Redis內建保護措施允許使用者在配置檔案中使用maxmemory選項,設定Redis最大佔用記憶體。如果達到此限制,Redis將開始返回錯誤給寫命令(但是將繼續接受只讀命令),或者當最大記憶體限制達到時也可以配置為驅逐鍵,在這種情況下Redis作為快取使用。

我們有文件描述Redis作為LRU快取使用


在Linux系統中,即使我有很多空閒記憶體,後臺儲存失敗報fork錯誤!

精闢答案:echo 1 > /proc/sys/vm/overcommit_memory :)

詳細回答:

Redis後臺儲存模式依賴現代作業系統的寫時拷貝技術。Redis fork(建立一個子程式)是父程式精確拷貝。子程式儲存資料到磁碟並且最終退出。從理論上講,子程式應該和父程式使用同樣多記憶體,作為父程式副本,但是得益於多數現代作業系統實現的寫時複製技術,父程式和子程式共享記憶體頁。記憶體頁在父程式或子程式改變時將被複制。當子程式儲存時,理論上所有頁面都可能改變,Linux無法提前告知子程式需要多少記憶體,因此如果overcommit_memory設定為0,fork將會失敗除非有足夠的空閒RAM真正複製父程式記憶體頁.結果是,如果你有3G Redis資料集,只有2G可用記憶體將會失敗。

overcommit_memory設定為1,意味著Linux 使用更樂觀方式fork,這確實是你所期望的Redis。

理解虛擬機器記憶體 (校對注:有興趣可以翻譯此文在併發網發表)”是紅帽經典文章,可以瞭解Linux虛擬記憶體怎麼工作,overcommit_memory和overcommit_ratio的替代品。這篇文章校正了proc(5)使用者手冊對overcommit_memory1和2配置正確含義。


Redis磁碟快照是不是原子操作?

是的,當伺服器不在執行命令時,Redis後臺儲存程式總是被建立,因此每個命令在RAM中是原子的,並且在磁碟快照過程也是原子的。


Redis是單執行緒的,我怎麼利用多CPU/核?

CPU基本不可能成為的Redis的瓶頸,因為通常Redis受限於記憶體或網路。例如使用Pipelining,Redis執行在普通的Linux系統上,每秒可以處理50萬請求,所以如果你的應用程式主要使用O(N) 或者 O(log(N))命令,幾乎不會使用太多的CPU。

然而為了最大限度利用CPU,你可以在一臺機器上啟動多個Redis例項,並把它們設定為不同伺服器。某些時候單個機器是不夠的,所以如果你想使用多個CPU,你可以提前考慮使用分片。

關於使用多Redis例項,你可以在Partitioning page找到更多的資訊


單個Redis例項最多可以儲存多少鍵?雜湊表、列表、集合和有序集合最大可以包含多少元素?

Redis最大可以處理2^32鍵,實踐測試每個例項最少可以處理2.5億鍵

每個雜湊表、列表、集合和有序集合可以容納2^32元素

換句話說,Redis極限容量就是系統可用記憶體


為什麼我的從例項與主例項擁有不同數量鍵?

如果你使用有生存週期的鍵,這就是正常現象。這就導致主從例項鍵的數量不一致原因。

  • 主例項在第一次與從例項同步時生成RDB檔案。
  • RDB檔案不包含已經過期的鍵,但是已經過期的鍵仍然在記憶體中。
  • 儘管這些鍵從邏輯上說已經過期失效,但是還在Redis主例項記憶體中,他們並不被識別為存在的,當增量或訪問這些鍵時這些鍵會被回收。儘管從邏輯上說這些鍵不是資料集一部分,但是INFO和DBSIZE命令結果包含這些資訊。
  • 當從例項讀取主例項生成的RDB檔案時,過期鍵不會被載入。

為很多鍵設定過期屬性,通常為使用者提供了在從例項上儲存更少鍵,但是實際上例項內容沒有邏輯區別。


Redis實際含義是什麼?

Redis是遠端資料字典伺服器(REmote DIctionary Server)。


你為什麼啟動Redis專案?

最初啟動Redis,是為了擴大LLOOGG。但是當我完成了基本服務端工作後,我喜歡把這個想法分享給其他人,然後Redis轉變成開源專案。 


相關文章