write smart proxy step by step 1 (理論簡介)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
REMOTE DICTIONARY SERVER

為什麼寫這系列?

前段時間《7月,redis迷情》裡面提到,我司線上 Redis Cluster + Smart Proxy 模式。我把代碼放到了個人github上,大家感興趣的可以下載使用。如果遇到問題,隨時開Issue,或是直接找我。支援命令有限制,README裡有詳細介紹。

# go get  github.com/dongzerun/smartproxy

# make && ./cmd/redis_proxy  -config_file=example.ini

為什麼要重寫呢,有如下原因:

1. 當前實現需要對輸入做字串轉化,大家知道在Golang中,大量 Byte[] To String 效能不高且對GC壓力較大。可以參考 Bitly 對 NSQ 的最佳化官方文檔。

2. 複用 Go Redis Driver,封裝網路層,導致存在無效處理流程,重寫後可以從底層最佳化。

3. Redis 在資料庫領域裡相當小巧,開發中介軟體有助於對資料庫的理解。

4. 按模組開發,附以 Go 的單元測試,加深對 Go語言的認知和效能調優。


新的 Proxy 目標

老的代理當前使用上沒問題,效能也足夠用。新的要實現如下功能

1. 支援 Redis Cluster 協議,屏蔽語言的差異,這是核心。

2. 命令檢測,對危險或是不支援的命令提前檢測。

3. 支援 Pipeline,這個使用情境還是很多,老的代理無法實現。

4. 更詳細的效能統計,內建 Http DashBoard 以供查詢。

5. 服務發現與註冊,支援 Zookeeper 和 Etcd。


Redis Client Protocol

Redis協議相比MySQL協議簡單太多,感興趣的同學可以查看相應驅動源碼,加深對協議的理解。Redis屬於文本協議,基於 Request-Response Model 模型,官方稱做 RESP (REdis Serialization Protocol) 。

Response Protol

RESP協議有五種應答類型,每部分以 CRLF(\\r\\n) 結尾

1. Simple Strings: 簡單字元應答以"+"開頭,跟隨字串資料,並以 CRLF 結尾


Simple Strings Reply

例中返回資料為+OK\\r\\n

2. Errors: 錯誤應答以"-"開頭,跟隨錯誤原因的字串,並以 CRLF 結尾


Errors Reply

例中返回資料為-ERR wrong number of arguments for 'get' command\\r\\n

3. Integers: 整數應答以":"開頭,跟隨整數值,並以 CRLF 結尾


Integers Reply

例中返回資料為:2\\r\\n

4. Bulk Strings: 字串應答以"$"開頭,跟隨真實資料的長度和資料


Bulk String Reply

例中返回資料為$3\\r\\nBAR\\r\\n

5. Arrays: 數群組類型應答以"*"開頭,跟隨多個 Bulk Strings的應答


Array Reply

例中返回資料為*4\\r\\n$1\\r\\nb\\r\\n$1\\r\\n$a\\r\\n$1\\r\\nd\\r\\n$-1\\r\\n, 其中最後一個-1表示對應 command 中最後一個 key 不存在

Command Protol

舉個最簡單的命令 SET FOOFOO  BAR,那麼用戶端實際發送給 Server 的資料為

*3\\r\\n$3\\r\\nSET\\r\\n$6\\r\\nFOOFOO\\r\\n$3\\r\\nBAR\\r\\n

使用 telnet 類比如下


set foofoo bar

最後的+OK表示命令執行成功,反回 simple string OK,也就是說 Command 行為和 Array Reply 一致。

Redis Cluster 簡介

官網有兩篇文章 cluster-spec 和 cluster-tutorial ,詳細講解了 Redis Cluster 實現原理和搭建,湖南TV提供了 Python 版的 Redis-trib,大家可以使用搭建和遷移 Cluster 資料很方便。如何搭建和 Cluster 內部選舉演算法這裡不做講解,需要注意 cluster-require-full-coverage 這個參數要設為 no

If this is set to yes, as it is by default, the cluster stops accepting writes if some percentage of the key space is not covered by any node. If the option is set to no, the cluster will still serve queries even if only requests about a subset of keys can be processed.

簡單來說,Cluster 將 Key(或是根據 hash tag) 按照 CRC16 處理得到 hash value,對值按 16384 模數,這樣會將資料均勻分到 16384 slots 中,屬於邏輯槽,邏輯 slots 再根據 Cluster-nodes.conf 確定具體屬於哪個物理主從對


cluster-nodes.conf
cluster info

使用 Cluster Info 命令可以看到當前叢集資訊,cluster_slots_assigned 表示當前已指派物理節點的 slots 數量,cluster_slots_ok 表示當前有多少個 slots 正常服務,fail和pfail分別表示當前節點誰為主觀宕機和客觀宕機的 slots 數量,cluster_size 表示叢集有多少個物理主從對,對參數更詳細的請參考官方文檔。

由於採用無中心的設計,用戶端隨機串連一個節點,發起請求。Redis 根據 Key 擷取 hash 值後模數,得到 Slot ID,在記憶體中尋找 Slot ID 當前屬於哪個物理節點。如果不是本機,那麼 Redis 返回用戶端一個 Errors Reply, 錯誤內容是一個 MOVE 重新導向,例如:

127.0.0.1:6494> get b

(error) MOVED 3300 10.10.10.178:6494

此時用戶端根據 MOVED 指令,去串連10.10.10.178:6494執行個體,發起同樣的請求,得到正確的資料。理想情況下,Smart 用戶端只需 MOVED 跳轉一次即可找到正確節點。

當 Slot 發生遷移時,Redis 會在源節點標記該 Slot 為 Migrating 狀態,同時標記目標節點該 Slot 為 Importing 狀態。當用戶端發起請求時,所有流量都會轉寄到源節點,如果資料存在那麼返回。如果資料不存在,那麼可能已經遷移到目標節點。源節點返回一個 -ASK 錯誤附加目標節點資訊,用戶端串連目標節點,先發起一個 ASKING 命令,再發送正常的請求。如果不先發送 ASKING 命令,那麼目標節點會認為是非法請求,返回 MOVED 重新導向。

Smart Proxy 設計思路

明白了 Redis Cluster 原理,那麼核心設計起來也就簡單多了。其它功能都是添枝加葉。具體模組劃分留到下一篇分享吧,每篇編寫一個模組,並附件詳細的 Go Test 和效能測試。

1. 定期擷取 Cluster Config 配置資訊,緩衝到 Proxy 記憶體中。

2. 對請求 Key 取 Hash Value後,查詢 Slots 配置,發送到指定後端節點。

3. 處理好 MOVED 和 ASK 兩個異常即可。


結語

這篇只講些理論基礎,後續再具體編碼,希望自已能堅持寫完~_~ 推薦大家一首歌《壓縮餅乾》來自大冰

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.