Redis hash tag 如何運作?

當您想要分配多個鍵到同一個槽位(slot)時,可以用 hash tag 來達到這個問題,但使用 hash tag 後,也的有許多的問題(例如 hotkey issue),需要特別去注意。

Jerry’s Notes
What’s next?
8 min readAug 3, 2022

--

首先必需先理解,Redis 儲存數據的方式,一個 Redis 集群,會包含 16384 個哈希槽(hash slot),當您在寫入數據時,會透過 CRC16(key) % 16384 的方式,來計算鍵 key 屬於哪個槽位(slot),進而將數據儲存在該槽位(slot)裡。

而當在 Redis 叢集模式(cluster mode enable)的運作模式下,會有多個分片組(shard),而每個分片組(shard),負責處理部份的槽位(slot),Redis 集群模式透過這個方式,來達到多個片組(shard)中的主節點,都能做寫入的操作。詳細請參考以下文檔。

!!! 簡單來說,在”叢集模式(cluster mode enable)下”,Redis 會將數據分散寫入到多個主節點上,而每一個主節點,會負責一部份的 slots,而在”非叢集模式下 (single node or replicanion mode)”,就全部集中在同一台主節點上。

為什麼要使用 Hash tag?

不過當您使用 msetmget 這類型命令時,由於這些命令具有原子性(atomic)操作的特定,所以當您存取的鍵值,若存在於多個節點上時(叢集模式 — cluster mode enable),就會出現錯誤,此時您可以使用 hash tag 的方式,將您的多個鍵值,在同一個 “槽位(slot)” 來操作,來實現這個目的。

Redis Hash tag 如何運行?

當您在存取特定鍵值時,Redis 只計算 “大括號 {xxxx}” 內字符串的哈希值,然後用該數據對特定 “槽位(slot)” 上存取。詳細請參考 Redis 官方文檔。

[+] Redis hash-tags:
https://redis.io/docs/reference/cluster-spec/#hash-tags

Ruby example code:

Hashes — 哈希值操作範例

舉例來說

當您以下的字串,使用相同 hash tag {aaaa},此時所取得的 hash tag 值,就是相同,也在存取到同一個 “槽位(slot)” 上,等同於在同一個 “分片(shard)” 上存取。

data00001:{aaaa}:code
data00002:{aaaa}:code
data00003:{aaaa}:code
data00004:{aaaa}:code

而當您的字串中,有多個 “大括號 {xxxx}” 時,依 Redis 原生文檔說明,會取第一個 {xxxx},來計算 hash tag 值,所以以下4個,是在不同的 “槽位(slot)” 上。

{data00001}:{aaaa}:code
{data00002}:{aaaa}:code
{data00003}:{aaaa}:code
{data00004}:{aaaa}:code

若您的字串中,”大括號 {xxxx}” 裡面又有包含其他 “大括號 {xxxx}” 時,例如下面範本,此時 Redis 會使用第一個找到的 “{“,以及第一個找到的 “}“ ,之間的字串,來計算哈希值。 以下面這個例子,就是使用 “data00001{aaaa” 來計算字符串的哈希值,所以在使用上要特別小心及注意。

{data00001{aaaa}}:code

此外,您可以透過 > CLUSTER KEYSLOT xxx 命令,來確認特定鍵,會在那一個 “槽位(slot)” 上。

Hash tags 會造成什麼問題?

當您的前端業務大量去使用 hash tag 時,容易造成您的數據集中在特定 ”槽位(slot)”上,換而言之,就是您的數據容易集中在特定 ”分片組(shard)”上,所以就容易出現 Hotkey issue,所以使用上也要特定注意及小心。

Hotkey issue — 什麼是Hotkey?

Issue: Frequently queried keys in Redis are hotkeys, and it can cause high requests resulting in bottleneck issue on specific nodes.

所謂的熱 Key 問題都是由於對某個 Key 的訪問量過大所產生的一些衍生問題。由於某個 Key 的數據一定是存儲到後端某台服務器的 Redis 單個實例上,如果對這個 Key 突然出現大量的請求操作,這樣就會造成流量過於集中,達到 Redis 單個實例處理上限,可能會導致 Redis 實例 CPU 使用率 100%,或者是網卡流量達到上限等,對系統的穩定性和可用性造成影響,或者更為嚴重出現服務器宕機,無法對外提供服務;更有甚者在出現 Redis 服務不可用之後,大量的數據請求全部落地數據庫查詢上,Redis 都已經頂不住了,數據庫也是分分鐘掛掉的節奏,這個是所謂的熱 Key 問題。

怎麼產生的?

1) 業務邏輯上,造成對特定 key 值 / slot 做大量存取的行為。

2) 使用 hash key 去大量存取特定 slot 的鍵值

hotkey造成的問題有那些?

•特定 shard / 特定節點特別忙碌。

•特定的 node 會特別忙

•節點效能上限。流量集中,達到服務器處理上限 (CPU、網絡 IO….等)。

•操作延遲。由於Redis單線程的特性,操作會影響在同一個 Redis 實例上其他 Key 的讀寫請求操作;

•操作延遲。大量 Redis 請求失敗,查詢操作可能打到數據庫,拖垮數據庫,導致整個服務不可用。

--

--

Jerry’s Notes
What’s next?

An cloud support engineer focus on troubleshooting with customer reported issue ,and cloud solution architecture.