Redis 實戰 —— 12. 降低記憶體佔用
阿新 • • 發佈:2021-02-02
#### 簡介
降低 Redis 的記憶體佔用有助於減少建立快照和載入快照所需的時間、提升載入 AOF 檔案和重寫 AOF 檔案時的效率、縮短從伺服器進行同步所需的時間(快照、 AOF 檔案重寫在 [持久化選項](https://mp.weixin.qq.com/s/YcVieEvc-IN5ybPAUXYM2w) 中進行了介紹,從伺服器同步在 [複製、處理故障、事務及效能優化](https://mp.weixin.qq.com/s/sTPKmNwyTZagMsnX-8UCow) 中進行了介紹),並且能讓 Redis 儲存更多的資料而無需新增額外的硬體。 `P208`
#### 短結構 (short structure) `P208`
Redis 為列表、集合、雜湊和有序集合提供了一組配置選項,這些選項可以讓 Redis 以更節約空間的方式儲存長度較短的結構(後面簡稱“短結構”)。 `P208`
在列表、雜湊和有序集合的長度較短或者體積較小的時候, Redis 可以選擇使用一種名為壓縮列表 (ziplist) 的緊湊儲存方式來儲存這些機構。壓縮列表是列表、雜湊和有序集合這 3 種不同型別的物件的一種非結構化 (unstructured) 表示:與 Redis 在通常情況下使用雙向連結串列表示列表、使用散列表表示雜湊、使用散列表加上跳錶 (skiplist) 表示有序集合的做法不同,壓縮列表會以序列化的方式儲存資料,這些序列化資料每次被讀取的時候都要進行解碼,每次被寫入的時候也要進行區域性的重新編碼,並且可能需要對記憶體裡面的資料進行移動。 `P209`
##### 壓縮列表表示 `P209`
本節以最簡單的列表進行觀察對比。
###### 雙向連結串列 `P209`
列表不進行壓縮時使用雙向連結串列 (doubly linked list) 進行儲存,連結串列的每個結點都有三個指標: `P209`
- 指向前一個結點的指標
- 指向後一個結點的指標
- 指向結點包含的字串值的指標
其中字串值又分為三個部分: `P209`
- 字串的長度
- 字串剩餘可用的位元組數
- 以空字元結尾的字串本身
可以發現未壓縮前,每儲存一個字串,最少需要 21 位元組的額外開銷 (overhead) 。(三個指標每個佔 4 個位元組,兩個整數每個佔 4 個位元組,字串結尾的空字元佔 1 個位元組) `P209`
###### 壓縮列表 `P209`
壓縮列表是由結點(非真實結點)組成的序列 (sequence) ,每個結點都由兩個長度值和一個字串組成。 `P209`
- 第一個長度值:前一個結點的長度,用於從後向前的遍歷(一般以一個位元組儲存)
- 第二個長度值:當前結點的長度(一般以一個位元組儲存)
- 字串:長度等於位元組數,沒有空字元
可以發現壓縮後,每儲存一個字串,最少需要 2 位元組的額外開銷。 `P210`
###### 使用壓縮列表編碼 `P210`
**不同結構關於使用壓縮列表的配置選項** `P210`
```properties
# 列表使用壓縮列表表示的限制條件
list-max-ziplist-entries 512
list-max-ziplist-value 64
# 雜湊使用壓縮列表表示的限制條件
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# 有序集合使用壓縮列表表示的限制條件
zset-max-ziplist-entries 512
zset-max-ziplist-value 64
```
其中, `...-entries` 選項說明列表、雜湊和有序集合在被編碼為壓縮列表的情況下,允許包含的最大元素數量; `...-value` 選項說明了壓縮列表每個結點的最大體積是多少位元組。當這些選項設定的限制條件中的任意一個被突破時, Redis 就會將對應的列表、雜湊和有序集合從壓縮列表編碼轉換為其他結構,而記憶體佔用也會因此增加,並且即使其將來重新滿足限制條件,也不會再轉換回壓縮列表。 `P210`
**除錯** `P210`
`OBJECT` 命令允許從內部檢視給定 key 的 Redis 物件, 它通常用在除錯(debugging) 或者瞭解為了節省空間而對 key 使用特殊編碼的情況。當將Redis 用於進行快取時,也可以通過 `OBJECT` 命令中的資訊,決定 key 的驅逐策略 (eviction policies) 。
- `OBJECT R