Redis Shared Object
redisObject
Redis 存儲的數據都使用 redisObject來封裝, 包括 string, hash, list, set, zset 在內的所有數據類型. 理解 redisObject 對內存優化非常有幫助

共享對象池 Shared object
共享對象池是指 Redis 內部維護 [0-9999] 的整數對象池. 創建大量的整數類型 redisObject 存在內存開銷, 每個 redisObject 內部結構至少佔 16 字節, 甚至超過了整數自身空間消耗. 所以 Redis 內存維護一個 [0-9999] 的整數對象池, 用於節約內存. 除了整數對象池, 其他類型如 list, hash, set, zset 內部元素也可以使用整數對性池. 因此開發中的滿足需求的前提下, 盡量使用整數對象以節省內存.
整數對象池在 Redis 中通過變量 REDIS_SHARED_INTEGERS 定義, 不能通過配置修改. 可以通過 object refcount 命令查看對象引用數驗證是否啟用整數對象池技術,
redis > set foo 100
OK
redis > object refcount foo
(integer) 2
redis > set bar 100
OK
redis > object refcount bar
(integer) 3
可看出 foo 直接使用共享池內整數對象, 因此引用數是2, 再設置鍵 bar等於 100 時, 引用數又變為3

為什麼開啟 maxmemory 和 LRU 淘汰策略後對象池無效?
LRU 算法需要獲取對象最後訪問的時間, 以便淘汰最長未訪問數據, 每個對象做後訪問時間存儲在 redisObject 對象的 lru 字段. 對象共享意味著多個引用更想同一個 redisObject, 這時 lru 字段也會被共享, 導致無法獲取每個對象的最後訪問時間. 如果沒有設置maxmemory, 直到內存被用盡 Redis 也不會觸發回收內存, 所以共享對象池可以正常工作.
共享對象池與 maxmemory + LRU 策略衝突, 使用時需要注意. 對於 ziplist 編碼的值對象, 即使內部數據為整數也無法使用更想對象池, 因為 zip;ist使用壓縮且內存連續的結構, 對象共享判斷成本過高
為什麼只有整數對象池?
首先整數對象池複用的機率最大, 其次對象共享的一個關鍵操作就是判斷想等性, Redis 之所以只有整數對象池, 是因為整數比較算法時間複雜度為 O(1), 只保留一萬個整數為了防止對象池浪費. 如果是字符串判斷相等性, 時間複雜度變為 O(n), 特別是常字符串更消耗性能(浮點數在 Redis 內部使用字符串存儲). 對於更複雜的數據結構如 hash, list 等, 相等性判斷需要 O(n^2). 對於單線程的 Redis 來說, 這樣的開銷雖然不合理, 因此 Redis 只保留整數共享對象池.