一文搞懂 Redis下降內存佔用方式

前言

Redis是當前比較熱門的NOSQL數據庫之一,和Memcache同樣,數據都是緩存在計算機內存中。徹底開源免費,遵照BSD協議,是一個高性能的key-value數據庫。經過在內存中讀寫數據,大大提升了數據讀寫速度,能夠說Redis是實現網站高併發不可或缺的一部分。redis

下降Redis的內存佔用有助於減小建立快照和加載快照所需的時間、提高載入AOF文件和重寫AOF文件時的效率、縮短從服務器進行同步所需的時間」,而且能讓Redis存儲更多的數據而無需添加額外的硬件。數據庫

本文將介紹如下3種很是有價值的下降Redis內存佔用的方法。數組

  • 短結構( short structure )
  • 分片結構( shared structure )
  • 打包存儲二進制位和字節

短結構

Redis爲列表、集合、散列、有序集合提供了一組配置選項,這些選項可讓redis以更節約的方式存儲較短的結構。緩存

ziplist壓縮列表(列表、散列、有序集合)

一般狀況下使用的存儲方式:bash

當列表、散列、有序集合的長度較短或者體積較小的時候,redis將會採用一種名爲ziplist的緊湊存儲方式來存儲這些結構。服務器

ziplist是列表、散列、有序集合這三種不一樣類型的對象的一種非結構化表示,它會以序列化的方式存儲數據,這些序列化的數據每次被讀取的時候都須要進行解碼,每次寫入的時候也要進行編碼。數據結構

雙向列表與壓縮列表的區別:併發

爲了瞭解壓縮列表比其餘數據結構更加節約內存,咱們以列表結構爲例進行深刻研究。高併發

典型的雙向列表性能

在典型雙向列表裏面,每一個值都都會有一個節點表示。每一個節點都會帶有指向鏈表前一個節點和後一個節點的指針,以及一個指向節點包含的字符串值的指針。

每一個節點包含的字符串值都會分爲三部分進行存儲。包括字符串長度、字符串值中剩餘可用字節數量、以空字符結尾的字符串自己。

例子:

倘若一個某個節點存儲了’abc’字符串,在32位的平臺下保守估計須要21個字節的額外開銷(三個指針+兩個int+空字符即:3*4+2*4+1=21)

由例子可知存儲一個3字節字符串就須要付出至少21個字節的額外開銷。

ziplist

壓縮列表是由節點組成的序列,每一個節點包含兩個長度和一個字符串。第一個長度記錄前一個節點的長度(用於對壓縮列表從後向前遍歷);第二個長度是記錄本當前點的長度;被存儲的字符串。

例子:

存儲字符串’abc’,兩個長度均可以用1字節來存儲,所以所帶來的額外開銷爲2字節(兩個長度即1+1=2)

結論:

壓縮列表是經過避免存儲額外的指針和元數據,從而達到下降額外的開銷。

intset整數集合(集合)

前提條件,集合中包含的全部member均可以被解析爲十進制整數。

以有序數組的方式存儲集合不只能夠下降內存消耗,還能夠提高集合操做的執行速度。

配置:

1 set-max-intset-entries 512 #限制集合中member個數,超出則不採起intset存儲複製代碼

性能問題

無論列表、散列、有序集合、集合,當超出限制的條件後,就會轉換爲更爲典型的底層結構類型。由於隨着緊湊結構的體積不斷變大,操做這些結構的速度將會變得愈來愈慢。 

分片結構

分片的本質就是基於簡單的規則將數據劃分爲更小的部分,而後根據數據所屬的部分來決定將數據發送到哪一個位置上。不少數據庫使用這種技術來擴展存儲空間,並提升本身所能處理的負載量。

結合前面講到的,咱們不難發現分片結構對於redis的重要意義。所以咱們須要在配置文件中關於ziplist以及intset的相關配置作出適當的調整。

回到頂部

分片式散列

散列分片主要是根據基礎鍵以及散列包含的鍵計算出分片鍵ID,而後再與基礎鍵拼接成一個完整的分片鍵。在執行hset與hget以及大部分hash命令時,都須要先將key(field)經過shardKey方法處理,獲得分片鍵纔可以進行下一步操做。

分片式集合

如何構造分片式集合纔可以讓它更節省內存,性能更增強大呢?主要的思路就是,將集合裏面的存儲的數據儘可能在不改變其原有功能的狀況下轉換成能夠被解析爲十進制的數據。根據前面所講到的,當集合中的全部成員都可以被解析爲十進制數據時,將會採用intset存儲方式,這不只可以節省內存,並且還能夠提升響應的性能。

例子:

倘若要某個大型網站須要存儲每一天的惟一用戶訪問量。那麼就可使用將用戶的惟一標識符轉化成十進制數字,再存入分片式set中。

打包存儲二進制位和字節

結合前面所講的分片技術,採用string分片結構爲大量連續的ID用戶存儲信息。

使用定長字符串,爲每個ID分配n個字節進行存儲相應的信息。

接下來咱們將採用存儲用戶國家、省份的例子進行講解:

倘若某個用戶須要存儲中國、廣東省這兩個信息,採用utf8字符集,那麼至少須要消耗5*3=15個字節。若是網站的用戶量大的話,這樣的作法將會佔用不少資源。接下來咱們採用的方法每一個用戶僅僅只須要佔用兩個字節就能夠完成存儲信息。

具體思路步驟:

  1. 首先咱們爲國家、以及各國家的省份信息創建相應的’信息表格’
  2. 將’信息表格’建好後,也意味着每一個國家,省份都有相應的索引號
  3. 看到這裏你們應該都想到了吧,對就是使用兩個索引做爲用戶存儲的信息,不過須要注意的是咱們還須要對這兩個索引進行相應的處理
  4. 將索引當作ASCII碼,將其轉換爲對應ASCII(0~255)所指定的字符
  5. 使用前面所講的分片技術,定長分片string結構,將用戶的存儲位置找出來(redis中一個string不能超過512M)
  6. 實現信息的寫入以及取出(getrange、setrange)


因爲平臺篇幅限制,爲了你們更好的閱讀,關於Redis的文檔小編已經打包整理好了,有感興趣的程序猿(媛),能夠加 QQ羣 538700182 私聊羣主 免費獲取

相關文章
相關標籤/搜索