Redis的常見問題

Redis與其他鍵值存儲有何不同?

Redis在鍵值數據庫中具有不同的演變路徑,其中值可以包含更覆雜的數據類型,並在這些數據類型上定義原子操作。Redis 數據類型與基本數據結構密切相關,並且直接向程序員公開,無需額外的抽象層。

 

Redis是一個內存數據庫但同時數據也存在於磁盤數據庫中,所以它代表了一種不同的折中,在數據集不大於內存的限制下實現了非常高的寫入和讀取速度。內存數據庫的另一個優點是,與磁盤上的相同數據結構相比,覆雜數據結構的內存表示更易於操作,因此Redis可以在內部覆雜性很小的情況下做很多事情。同時,兩種磁盤存儲格式(RDB和AOF)不需要適用於隨機訪問,因此它們是緊湊的並且總是以append-only的方式生成(即使 AOF日志輪換也是一種append-only方式,因為新版本是從內存中的數據副本生成的)。然而,與傳統的磁盤存儲相比,這種設計也涉及不同的挑戰。作為內存中的主要數據表示,必須小心處理Redis操作,以確保磁盤上總是有一個更新的數據集版本。

Redis的內存占用情況是怎樣的?

舉幾個例子(以下均是基於64位系統得到的實例):

 

  • 一個空的實例約占用3MB的內存。
  • 100萬個小鍵->字符串-值對約占用85MB的內存。
  • 100萬個鍵->哈希值,用5個字段表示一個對象,約占用160MB的內存。

測試用例的規模是微不足道的。我們可以使用redis-benchmark工具生成隨機數據集,然後用INFO memory命令檢查所用空間。

 

64位系統將比32位系統使用更多的內存來存儲相同的鍵,尤其是如果鍵和值都很小的情況下,這種現象更為明顯。這是因為指針在64位系統中需要8個字節。不過好處是你可以在64位系統中擁有大量的內存,所以為了運行大型的Redis服務器,或多或少需要64位系統。

為什麽Redis將其整個數據集保存在內存中?

在過去,Redis的開發者嘗試了虛擬內存和其他系統,以允許使用比RAM更大的數據集,我們期望能做好“內存提供數據,磁盤用於存儲”這件事。所以現在還沒有計劃為Redis創建一個磁盤後端。畢竟Redis的大部分功能都是其當前設計的直接結果。

 

如果你真正的問題不是所需的總內存,而是你需要將你的數據集分成多個Redis實例,請閱讀本文檔中的分區頁面,以獲得更多信息。

 

Redis的讚助商Redis Ltd.公司開發了一個名為“Redis on Flash”的解決方案,該解決方案使用混合RAM/flash的方法來處理具有偏向訪問模式的大型數據集。您可以查看他們的產品以了解更多信息,但此功能並不屬於Redis開源代碼庫的部分。

可以將Redis與基於磁盤的數據庫一起使用嗎?

答案是肯定的,一種常見的設計模式是在Redis中獲取寫入量很大的小數據(以及您需要Redis數據結構以有效的方式為您的問題建模的那些數據),以及將大塊數據放入SQL或最終一致的磁盤數據庫中。同樣,有時Redis被用來在內存中獲取存儲在磁盤數據庫中的相同數據子集的另一個副本。這看起來類似於緩存,但實際上是一個更高級的模型,因為通常Redis數據集與磁盤數據庫的數據集一起更新。

如何減少Redis的整體內存使用量?

如果可以的話,請使用Redis 32位實例。還要充分利用小哈希、列表、排序集和整數集,因為Redis能夠在包含少數元素的特殊情況下以更緊湊的方式表示這些數據類型。另外,你也可以在內存優化頁面上獲取更多相關的信息。

如果Redis的內存不足怎麽辦?

Redis具有內置保護功能,它允許用戶設置內存使用的最大限制,使用maxmemory配置文件中的選項來設定Redis可以使用的最大內存。如果達到此限制,Redis將開始對寫入的命令回覆錯誤(但將繼續接受只讀命令)。

 

你也可以配置Redis在達到最大內存限制時的逐出密鑰。

在Linux上後台保存失敗,出現fork()錯誤?

Redis後台的保存模式依賴於現代操作系統中fork調用的copy-on-write語義:Redis forks(創建子進程)是父進程的精確副本。子進程將DB轉儲到磁盤上,然後退出。理論上,子進程應該使用與父進程一樣多的內存,但實際上,由於大多數現代操作系統實現了copy-on-write語義,父進程和子進程將共享公共內存頁。只有當一個頁面在子進程或父進程中發生變化時,它才會被覆制。由於理論上所有的頁面都可能在子進程保存時發生變化,Linux無法提前知道子進程將占用多少內存,所以如果將overcommit_memory設置為0,分叉將會失敗,除非你有足夠可用的RAM來真正覆制所有父內存頁面。也就是說,如果您有一個3 GB的Redis數據集,而只有2 GB的可用內存,那麽將會導致分叉失敗。

 

將overmit\u memory設置為1會讓Linux以更樂觀的分配方式執行fork,這也確實才是您想要的Redis

要了解Linux虛擬內存的工作原理以及overcommit_memory和overcommit_ratio的其他替代方案,您可以參考Red Hat Magazine的經典文章《理解虛擬內存》。您也可以參考手冊頁,了解可用值的解釋。

Redis如何使用多個CPU或內核?

Redis通常受內存或網絡限制,CPU成為其瓶頸的情況倒並不常見。例如,當使用管道時,一個運行在普通Linux系統上的Redis實例每秒可以發送100萬個請求,所以如果你的應用程序主要使用O(N)或O(log(N))命令,它幾乎不會使用太多的CPU。

 

不過,為了最大限度地提高CPU利用率,您可以在單盒(single box)中啟動多個Redis實例,並將它們視為不同的服務器。在某些情況下,單盒(single box)可能是不夠的,因此如果您想使用多個CPU,可以開始考慮更早地進行切分。

 

從4.0版本開始,Redis已經開始實現線程操作。但目前這僅限於在後台刪除對象和阻止通過Redis模塊實現的命令。對於後續版本,計劃是使Redis越來越多的線程化。

單個Redis實例最多可以容納多少個鍵?哈希、列表、集合和排序集合中元素的最大數量是多少?

Redis最多可以處理2^32個鍵,經過實踐測試,每個實例至少可以處理2.5億個鍵。

 

每個哈希、列表、集和排序集可以容納2^32個元素。

 

換句話說,您的最大限制可能是系統中的可用內存。

為什麽我的副本與主實例鍵的數量不同?

如果您使用有效期有限的鍵(Redis過期),這是正常現象。這是因為:

 

  • The primary在第一次與副本同步時生成一個 RDB 文件。
  • RDB文件不會包含在The primary中已經過期但仍存在於內存中的鍵。
  • 即使在邏輯上過期,這些鍵仍在Redis主數據庫the Redis primary的內存中。稍後將以增量或顯式方式在訪問時回收它們的內存。雖然這些鍵在邏輯上不是數據集的一部分,但它們在INFO輸出和DBSIZE命令中被計算在內。
  • 當副本讀取主數據庫The primary生成的RDB文件時,這組鍵將不會被加載。

 

因此,具有許多過期鍵的用戶通常會在副本中看到較少的鍵。但是,從邏輯上講,The primary和副本將具有相同的內容。

聯係虹科幫您解決難題

Let's have a chat