摘要:讀取和寫入的速度基本一致,差別不大回到這個問題,對于和該如何選擇呢我比較贊同下面這個答案具體使用哪種數據結構,其實是需要看你要存儲的數據以及使用場景。
在stackoverflow 看到一個問題,Redis strings vs Redis hashes to represent JSON: efficiency?內容如下:
string 和 hash 直觀測試I want to store a JSON payload into redis. There"s really 2 ways I can do this:
One using a simple string keys and values.
key:user, value:payload (the entire JSON blob which can be 100-200 KB)
SET user:1 payload
Using hashes
HSET user:1 username "someone"
HSET user:1 location "NY"
HSET user:1 bio "STRING WITH OVER 100 lines"Keep in mind that if I use a hash, the value length isn"t predictable. They"re not all short such as the bio example above.
Which is more memory efficient? Using string keys and values, or using a hash?
首先我們先測試用數據測試一下,測試數據結構如下:
values = { "name": "gs", "age": 1 }
使用for 生成10w個key,key的生成規則為:
for i in range(100000): key = "object:%d" % i
把數據分別以hash 和 string(values 使用 json encode 為string )的形式存入redis。
結果如下:
hash 占用 10.16Mstring 占用 10.15M
這看起來和我們印象中hash 占空間比較大的觀念不太一致,這是為什么呢?
這里是因為Redis 的hash 對象有兩種編碼方式:
ziplist(2.6之前是zipmap)
hashtable
當哈希對象可以同時滿足以下兩個條件時, 哈希對象使用 ziplist 編碼:
哈希對象保存的所有鍵值對的鍵和值的字符串長度都小于 64 字節;
哈希對象保存的鍵值對數量小于 512 個;
不能滿足這兩個條件的哈希對象需要使用 hashtable 編碼。上述測試數據滿足這兩個條件,所以這里使用的是ziplist來存儲的數據,而不是hashtable。
注意ziplist
這兩個條件的上限值是可以修改的, 具體請看配置文件中關于 hash-max-ziplist-value 選項和 hash-max-ziplist-entries 選項的說明。hash-max-ziplist-entries for Redis >= 2.6
hash-max-ziplist-value for Redis >= 2.6
ziplist 編碼的數據底層是使用壓縮列表作為底層數據結構,結構如下:
hash 對象使用ziplist 保存時,程序會將保存了鍵的ziplist節點推入到列表的表尾,然后再將保存了值的ziplist節點推入列表的表尾。
使用這種方式保存時,并不需要申請多余的內存空間,而且每個Key都要存儲一些關聯的系統信息(如過期時間、LRU等),因此和String類型的Key/Value相比,Hash類型極大的減少了Key的數量(大部分的Key都以Hash字段的形式表示并存儲了),從而進一步優化了存儲空間的使用效率。
在這篇redis memory optimization官方文章中,作者強烈推薦使用hash存儲數據
Use hashes when possiblehashtableSmall hashes are encoded in a very small space, so you should try representing your data using hashes every time it is possible. For instance if you have objects representing users in a web application, instead of using different keys for name, surname, email, password, use a single hash with all the required fields.
But many times hashes contain just a few fields. When hashes are small we can instead just encode them in an O(N) data structure, like a linear array with length-prefixed key value pairs. Since we do this only when N is small, the amortized time for HGET and HSET commands is still O(1): the hash will be converted into a real hash table as soon as the number of elements it contains will grow too much (you can configure the limit in redis.conf).
This does not work well just from the point of view of time complexity, but also from the point of view of constant times, since a linear array of key value pairs happens to play very well with the CPU cache (it has a better cache locality than a hash table).
hashtable 編碼的哈希對象使用字典作為底層實現, 哈希對象中的每個鍵值對都使用一個字典鍵值對來保存:
字典的每個鍵都是一個字符串對象, 對象中保存了鍵值對的鍵;
字典的每個值都是一個字符串對象, 對象中保存了鍵值對的值。
hashtable 編碼的對象如下所示:
第二次測試values = { "name": "gs", "age": 1, "intro": "long..long..long..string" }
第二次測試方式和第一次一樣,只是把測試數據中加了一個大的字符串,以保證hash 使用hashtable 的方式存儲數據
結果如下:
hashtable: 1.13Gstring: 1.13G
基本一樣,這里應該主要是Hash類型極大的減少了Key的數量(大部分的Key都以Hash字段的形式表示并存儲了),從而進一步優化了存儲空間的使用效率。
NOTE: 讀取和寫入的速度基本一致,差別不大
回到這個問題,對于string 和 hash 該如何選擇呢?
我比較贊同下面這個答案:
具體使用哪種數據結構,其實是需要看你要存儲的數據以及使用場景。
如果存儲的都是比較結構化的數據,比如用戶數據緩存,或者經常需要操作數據的一個或者幾個,特別是如果一個數據中如果filed比較多,但是每次只需要使用其中的一個或者少數的幾個,使用hash是一個好的選擇,因為它提供了hget 和 hmget,而無需取出所有數據再在代碼中處理。
反之,如果數據差異較大,操作時常常需要把所有數據都讀取出來再處理,使用string 是一個好的選擇。
當然,也可以聽Redis 的,放心的使用hash 吧。
還有一種場景:如果一個hash中有大量的field(成千上萬個),需要考慮是不是使用string來分開存儲是不是更好的選擇。
參考鏈接[1] Redis strings vs Redis hashes to represent JSON: efficiency?: https://stackoverflow.com/que...
[2] redis memory optimization: https://redis.io/topics/memor...
[3] Redis 設計與實現: http://redisbook.com/preview/...
最后,感謝女朋友支持和包容,比??
也可以在公號輸入以下關鍵字獲取歷史文章:公號&小程序 | 設計模式 | 并發&協程
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44109.html
摘要:所以查閱官方文檔以及他人造好的輪子,總結了一些面試和學習中你必須掌握的問題。在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。 昨天寫了一篇自己搭建redis集群并在自己項目中使用的文章,今天早上看別人寫的面經發現redis在面試中還是比較常問的(筆主主Java方向)。所以查閱官方文檔以及他人造好的輪子,總結了一些redis面試和學習中你必須掌握的問題。...
閱讀 3226·2021-10-13 09:40
閱讀 3688·2019-08-30 15:54
閱讀 1309·2019-08-30 13:20
閱讀 2993·2019-08-30 11:26
閱讀 475·2019-08-29 11:33
閱讀 1099·2019-08-26 14:00
閱讀 2356·2019-08-26 13:58
閱讀 3366·2019-08-26 10:39