閱讀495 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《Redis官方文檔》 FAQ

為什麼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值。

可以參考Redis as an LRU cache

在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實例請參考Partitioning page

單個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就變成了一個開源的項目。

最後更新:2017-05-19 18:01:48

  上一篇:go  Java class.getResource()的用法
  下一篇:go  Java 8 新特性