---
# System prepended metadata

title: 10.Scaling Redis
tags: [Redis]

---

---
tags: Redis
---
# 10.Scaling Redis
* 擴展讓redis能處理更大資料根更複雜的運算


---

## 1. Scaling reads

1. 使用第9章的短結構
2. 根據程式需要查詢的類型, 選擇能提供這種查詢最適當的類型. 比方：不要把LISTs 當 SETs
3. 較大的資料在寫進redis前先比較 lz4、gzip、bzip2, 看哪一個壓縮效果跟性能最好
4. 新增 read-only slave servers
    * 新增方式：將 redis config檔增加 slaveof host port, 再將 host、port改為主 redis的資訊
    * 疑慮：若連接太多 slave, 主服務器會需要發送太多快照, 使得主服務延遲
        * 解決方式：
            1. 以下圖的結構減少 redis master要傳送快照給slave的數量
        ![](https://i.imgur.com/oV76wrZ.png)
            2. 先進行壓縮, 減少要傳送的資料量. 用SSH to tunnel的連線可降低頻寬、使用openVPN進行壓縮
    * Redis sentinel：可以配合redis的複製功能使用, 當master故障時能立刻進行轉移
        * sentinel監視服務：向 master 發送 PUBLISH/SUBSCRIBE, 並向 master、slave發送PING來識別所有可用的slave. 當 master當機時, sentinel就可以通過有的資訊來選出新的master



---

## 2. Scaling writes and memory capacity

用分片(sharding in the context, 第9章的手法)的機制不僅可以增加記憶體的總數量, 同時也能在寫性能達到上限時,提升redis的寫性能. 本單元主要通過分片來擴展 redis

1. 確認是否已用盡所有方式來降低記憶體, 並盡可能減少需要寫入的資料量
    * 檢查程式是用最少的redis讀取量
    * 將無關的功能移到其他服務器上(參考ch5)
    * 在對redis寫入前先整理好要寫入的資料(參考ch6)
    * 用 lock 取代 WATCH/MULTI/EXEC(會有速度限制), 也可以使用ch11的Lua
    * 如果使用 AOF, 硬碟會將所有動作數據都儲存起來, 這需要花費一定時間, 因此指另可以多但一定要簡短

2. 處理分片(shard)的配置訊息(configuration)
    1. 使用python裝飾器獲得配置訊息(參考ch5), 接著把該配置訊息與已經有的進行比對, 根據比對結果來決定是否創新的連接, 根據ch5 信息儲存的格式為 config:redis:<component>
    ![](https://i.imgur.com/53cnM2d.png)

    2. 根據分片的信息來獲得連線, 若裝飾器不能使用則可以參考此方法
    ![](https://i.imgur.com/rCtjY5p.png)

    3. 通過2的get_sharded_connection, 模仿裝飾器寫出能自動創建分片的程式,並且還能直接傳遞連線給底層函數
    ![](https://i.imgur.com/2sGHHlt.png)
    舉例：將 Sets 分到16台機器上, 這些機器的配置會被編成Json字串並儲存從config:redis:unique:0 到 config:redis:unique:15, 至於每天的呼叫次數會被儲存到沒有被分片的redis的y config:redis:unique
    ![](https://i.imgur.com/KSWtkXe.png)


---


## 3. Scaling complex queries
查詢比讀寫更複雜,因此只對數據做分片是不夠的

1. 通過添加 query slave 來擴展搜尋量
    * 根據ch7搜尋需要使用到 SUNIONSTORE, SINTERSTORE, SDIFFSTORE, ZINTERSTORE, and/or ZUNIONSTORE, 這些都需要對 redis 進行寫入, 因此需要先將 slave 的 slave-read-only 從預設的 yes 改為 no, 如此搜尋就能在 slave 上進行, 要注意到搜尋的結果只會暫存在執行搜尋的機器上, 因此若有需要重複查詢需要執行些定期持久化操作

2. Scaling search index size
    數據量超過記憶體時採取的方法
    * 為了將搜尋要求進行分片, 先將搜尋index進行分片, 確保每個索引文檔內的所有數據都會儲存在同一分片 (方法參考 ch7 index_document()), 如此只要對分片進行查詢就能獲得搜尋結果. 搜尋方法由索引的類型分為 **SORT-based 和 ZSET-based**.
    * **SHARDING SORT-BASED SEARCH**(基於SORT的搜尋操作進行分片)
        1. 編寫一個能在單個分片上執行查詢的程式
        ![](https://i.imgur.com/KTatqZD.png)
        ![](https://i.imgur.com/uSBDKPK.png)
            search_get_values能從單個分片裡獲得所有必需的訊息
        2. 在所有分片上執行1.的查詢程式
        下圖的get_shard_results會一個接一個對所有分片進行搜尋, 要注意為了對所有分片進行搜尋num需要是正確的分片總數
        ![](https://i.imgur.com/XFZeLFA.png)

        3. 對各分片的查詢結果進行合併, 選出想要的部分結果
        下圖重新對所有結果進行排序, 注意數字及非數字排序之間的區別, 並謹慎處理缺失及排數字時遇到非數字的值
        ![](https://i.imgur.com/Hrhib8J.png)
    * **SHARDING ZSET-BASED SEARCH**
        1. 根據 Sets 來對所有分片進行搜尋
        包裝  search_and_zsort() (ch7) 在 ZSETs, 比10.5還更簡單, 他忽略沒有分值的結果, 直接從暫存後的 Sets 中獲得帶有值的結果
        ![](https://i.imgur.com/h1D8Qd7.png)
        2. 對每個分片進行搜尋後, 接著合併所有分片結果
        ![](https://i.imgur.com/nVEBPmd.png)
        ![](https://i.imgur.com/6LofhGV.png)

    
