---
# System prepended metadata

title: CH9. Reducing memory use
tags: [Redis]

---

---
tags: Redis
---
# CH9. Reducing memory use
降低內存佔用優點
* 減少創建快照和加載快照所需的時間
* 提升寫入 AOF 文件和重寫 AOF 文件時的效率
* 縮短從服務器進行同步所需的時間
## 9.1 Short Structures
* LISTs. SETs. HASHs. ZSETs
* 在LISTs. HASHs. ZSETs 長度較短時，可以使用ziplist來儲存
* ziplist: unstructured
    * LIST: doubly linked list
    * HASH: hash table
    * ZSET: hash table + skiplist
    * 上面三種每次被讀取的時候都要進行解碼，每次被寫入的時候也要進行局部的重新編碼，並且可能需要對內存的數據進行移動
* doubly linked list: 
    * 三個指針
        * 指向前一個node的指針
        * 指向後一個node的指針
        * 指向node包含的字符串值的指針
    * 字符串值
        * 字符串的長度
        * 字符串剩餘可用的字節數
        * 以空字符結尾的字符串本身
    * 3 * 4 + 2 * 4 + 1 = 21
![](https://i.imgur.com/UeI6c8A.png)
* ziplist:
    * 压缩列表是由结点（非真实结点）组成的序列 (sequence) ，每个结点都由两个长度值和一个字符串组成。
    * node組成的序列，每個node都由兩個長度值和一個字符串組成
    * 2
    * 压缩列表是通过避免存储额外的指针和元数据，从而达到降低额外的开销。
    * 耨過避免儲存額外的指針和元數據，從而達到降低額外的開心
* The intset encoding for SETs
    * 如果集合的所有成員都可以被解析為十進位整數，並且成員的數量足夠少，Redis 就會以有序整數數組的方式存儲集合，稱為intset
    * 降低內存消耗、提升所有 SET 操作的執行速度

* Performance issues for long ziplists and intsets
將 ziplist 的長度限制在 1024 個元素內，並且每個元素不能超過 64 個字節，對於大多數這種配置可兼顧低內存佔用和高性能兩個優點 

## 9.2 Sharded structures
* sharding 本質上就是基於某些簡單的規則將數據劃分為更小的部分，然後根據數據所屬的部分來決定將數據發送到哪個位置
* 這種技術可以擴展儲存空間並提高所能處理的負載量
* value X 儲存到 key Y 里面，而是將 value X 儲存到 key Y:shardid 裡面。
* Lists 在不使用 Lua 腳本的狀況下進行分配非常困難
* ZSETs 相關指令需要對 ZSET 的所有分片進行操作才能計算出指令的最終結果，所以這些操作無法運行的像普通的 SET 操作那麼快，因此對 ZSET 進行分片的作用不大
* HASHes 
    把 HASH 的 key 作為一個信息源，透過 hash function 計算出一個值
    根據需要儲存的 key 的總數量與每個 key 需要儲存的 key 數量，計算出所需的分片數
    使用分片數和 hash 決定應該 key 儲存到哪個分片裡面
![](https://i.imgur.com/SleCC9L.png)

* SETs
如果集合的所有成員都可以被解析為十進位整數，採用 intset 再存入sharded sets

## 9.3 Packing bits and bytes
* 通過四個命令，可以在不對數據進行壓縮的情況下，使用 Redis 字符串以盡可能緊湊的格式去儲存
    * GETRANGE: 用於讀取被儲存字符串的其中一部分內容
    * SETRANGE: 用於對儲存在字符串裡面的其中一部分內容進行設置
    * GETBIT: 用於獲取字符串裡面某個二進制位的值
    * SETBIT: 用於對字符串裡面某個二進制位進行設置
* 假如某個用戶需要儲存中國、廣東省這兩個信息，採用 utf-8，那麼至少需要消耗 5*3=15 個字節。用新的方式只需要 2 個字節
