最近在排查一個線上問題,發現redis使用了一個hash key裡面儲存了600w的filed,為啥這麼多就是因為他把一個結構體中的欄位分成了多個filed儲存。下面來看看到底應該怎麼設計比較合理。
一、問題一種使用簡單的字串鍵和值。 鍵:使用者,值:payload(整個JSON,可以為100-200 KB)SET user:1 payload
使用雜湊
HSET user:1 username "someone" HSET user:1 location "NY" HSET user:1 bio "STRING WITH OVER 100 lines"
請記住,如果使用雜湊,則值長度是不可預測的。它們並不都是短的,例如上面的bio示例。哪個記憶體效率更高?使用字串鍵和值,還是使用雜湊?
INCR id:usersSET user:{id} '{"name":"Fred","age":25}'SADD users {id}
一般來說,在大多數情況下,這可能是最好的方法。如果物件中有很多欄位,一個物件不會與其他物件巢狀,並且您一次只能訪問一小部分欄位,那麼選擇選項1可能不是很好。
優點:被認為是“良好實踐”。每個物件都是具有使用者資訊的Redis key。JSON解析速度很快,尤其是當您需要一次訪問此Object的多個欄位時。
缺點:當您只需要訪問一個欄位時,速度較慢。
2、將每個物件的屬性儲存在Redis雜湊中。
INCR id:usersHMSET user:{id} name "Fred" age 25SADD users {id}
優點:被認為是“良好實踐”。每個物件都是具有使用者資訊的Redis key。無需解析JSON字串。
缺點:當您需要訪問物件中的所有/大多數字段時,速度可能會變慢。同樣,巢狀物件(物件內的物件)也無法輕鬆儲存。
3、將每個物件作為JSON字串儲存在Redis雜湊中。
INCR id:usersHMSET users {id} '{"name":"Fred","age":25}'
這使您可以進行合併,並且僅使用兩個鍵,而不是很多鍵。明顯的缺點是您不能在每個使用者物件上設定TTL(以及其他內容),因為它只是Redis雜湊中的一個欄位,而不是具有使用者資訊的Redis key。
優點:JSON解析速度很快,尤其是當您需要一次訪問此Object的多個欄位時。減少主鍵名稱空間的“汙染”。
缺點:當您有很多物件時,記憶體使用量與#1差不多。當您只需要訪問單個欄位時,速度比#2慢。可能不被視為“良好做法”。
4 、將每個物件的每個屬性儲存在專用key中。
INCR id:usersSET user:{id}:name "Fred"SET user:{id}:age 25SADD users {id}
根據上面的解釋,幾乎永遠不會選擇此方案(除非Object的屬性需要具有特定的TTL或其他內容)。
優點:物件屬性是具有使用者資訊的Redis key,對於您的應用程式來說可能並不算過大。
缺點:速度慢,佔用更多記憶體,並且不被視為“最佳實踐”。主鍵名稱空間受到很多汙染。
三、總結方案4通常不是首選。方案1和2非常相似,而且都很常見。我更喜歡選項1(通常來說),因為它允許您儲存更復雜的物件(具有多層巢狀等)。當您真正關心不汙染主鍵名稱空間時,可以使用方案3。