您好,登錄后才能下訂單哦!
這篇文章主要介紹了Redis為什么要避免big key,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Redis 執行命令是單線程的,這意味著 Redis 操作「big key」有阻塞的風險。
big key 通常指的是 Redis 存儲的 value 過大。包括:
單個 value 過大。如 200M 大小的 String。
集合元素過多。如 List、Hash、Set、ZSet 中有幾百、上千萬數據。
舉個例子,假設我們有一個 200M 大小的 String key,名稱為「foo」。
執行如下命令
127.0.0.1:6379> GET foo
當返回結果時,Redis 會分配 200m 的內存,并執行 memcpy 拷貝。
void _addReplyProtoToList(client *c, const char *s, size_t len) { ... if (len) { /* Create a new node, make sure it is allocated to at * least PROTO_REPLY_CHUNK_BYTES */ size_t size = len < PROTO_REPLY_CHUNK_BYTES? PROTO_REPLY_CHUNK_BYTES: len; // 分配內存(例子中為 200m) tail = zmalloc(size + sizeof(clientReplyBlock)); /* take over the allocation's internal fragmentation */ tail->size = zmalloc_usable_size(tail) - sizeof(clientReplyBlock); tail->used = len; // 內存拷貝 memcpy(tail->buf, s, len); listAddNodeTail(c->reply, tail); c->reply_bytes += tail->size; closeClientOnOutputBufferLimitReached(c, 1); }}
而 Redis 輸出 buf 為 16k
// server.h#define PROTO_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */typedef struct client { ... char buf[PROTO_REPLY_CHUNK_BYTES];} client;
這意味著 Redis 無法單次返回響應數據,需要注冊「可寫事件」,從而觸發多次 write 系統調用。
這里有兩個耗時點:
分配大內存(也可能釋放內存,如 DEL 命令)
觸發多次可寫事件(頻繁執行系統調用,如 write、epoll_wait)
那么,如何找出 big key 呢?
如果 slow log 出現了簡單命令,如 GET、SET、DEL,大概率是出現了 big key。
127.0.0.1:6379> SLOWLOG GET 3) (integer) 201323 // 單位微妙 4) 1) "GET" 2) "foo"
其次,可以通過 Redis 分析工具來查找 big key。
$ redis-cli --bigkeys -i 0.1 ... [00.00%] Biggest string found so far '"foo"' with 209715200 bytes -------- summary ------- Sampled 1 keys in the keyspace! Total key length in bytes is 3 (avg len 3.00) Biggest string found '"foo"' has 209715200 bytes 1 strings with 209715200 bytes (100.00% of keys, avg size 209715200.00) 0 lists with 0 items (00.00% of keys, avg size 0.00) 0 hashs with 0 fields (00.00% of keys, avg size 0.00) 0 streams with 0 entries (00.00% of keys, avg size 0.00) 0 sets with 0 members (00.00% of keys, avg size 0.00) 0 zsets with 0 members (00.00% of keys, avg size 0.00)
對于 big key,有以下幾點建議:
1.業務中盡量避免 big key 出現。當出現 big key 時,你要判斷這樣設計是否合理,又或者是出現了 bug。
2.將 big key 拆分為多個小 key。
3.使用替代命令。
如果 Redis 版本大于 4.0,可使用 UNLINK 命令替代 DEL。Redis 版本大于 6.0,可開啟 lazy-free 機制。將釋放內存操作,放到后臺線程執行。
LRANGE、HGETALL 等替換為 LSCAN、HSCAN 分次獲取。
但我還是建議在業務中避免 big key。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Redis為什么要避免big key”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。