Redis效能最佳化的18招

苏三说技术發表於2024-11-19

前言

Redis在我們的日常開發工作中,使用頻率非常高,已經變成了必不可少的技術之一。

Redis的使用場景也很多。

比如:儲存使用者登入態,做限流,做分散式鎖,做快取提升資料訪問速度等等。

那麼問題來了,Redis的效能要如何最佳化?

為了充分發揮Redis的效能,這篇文章跟大家一起聊聊Redis效能最佳化的18招,希望對你會有所幫助。

1. 選擇合適的資料結構

Redis支援多種資料結構,如字串、雜湊、列表、集合和有序集合。根據實際需求選擇合適的資料結構可以提高效能。

如果要儲存使用者資訊,考慮使用雜湊而不是多個字串:

jedis.hset("user:1001", "name", "Alice");
jedis.hset("user:1001", "age", "30");

這樣可以高效地儲存和訪問多個屬性。

2. 避免使用過大的key和value

較長的key和value會佔用更多記憶體,還可能影響效能。

保持key簡短,並使用簡潔的命名約定。

比如:
將“user:1001:profile”簡化為“u:1001:p”。

還可以做壓縮等其他最佳化。

如果對大key問題,比較感興趣可以看看我的另一篇文章《從2s最佳化到0.1s,我用了這5步》,裡面有非常詳細的介紹。

3. 使用Redis Pipeline

對多個命令的批次操作,使用Pipeline可以顯著降低網路延遲,提升效能。

比如,批次設定key可以這樣做:

Pipeline p = jedis.pipelined();
for (int i = 0; i < 1000; i++) {
    p.set("key:" + i, "value:" + i);
}
p.sync();

這樣一次性可以傳送多個命令,減少了網路往返時間,能夠提升效能。

4. 控制連線數量

過多的連線會造成資源浪費,使用連線池可以有效管理連線數量。

比如,使用JedisPool:

JedisPool pool = new JedisPool("localhost");
try (Jedis jedis = pool.getResource()) {
    jedis.set("key", "value");
}

有了連線池,這樣連線就會被複用,而不是每次都建立新連線,使用完之後,又放回連線池。

能有效的節省連線的建立和銷燬時間。

5. 合理使用過期策略

設定合理的過期策略,能防止記憶體被不再使用的資料佔滿。

例如,快取熱點資料可以設定過期時間。

比如,對會話資料設定過期時間:

jedis.setex("session:12345", 3600, "data");

Redis內部會定期清理過期的快取。

6. 使用Redis叢集

資料量增大時,使用Redis叢集可以將資料分散到多個節點,提升併發效能。

可以將資料雜湊分片到多個Redis例項。

這樣可以避免單個Redis例項,資料太多,佔用記憶體過多的問題。

7. 充分利用記憶體最佳化

選擇合適的記憶體管理策略,Redis支援LRU(Least Recently Used)策略,可以自動刪除不常用的資料。

比如,配置Redis的maxmemory:

maxmemory 256mb
maxmemory-policy allkeys-lru

8. 使用Lua指令碼

Lua指令碼讓多條命令在Redis中原子性執行,減少網路延遲。

比如,使用Lua防止多個命令的網路延遲:

EVAL "redis.call('set', KEYS[1], ARGV[1]) return redis.call('get', KEYS[1])" 1 "key" "value"

使用Lua指令碼,可以保證Redis的多個命令是原子性操作。

9. 監控與調優

使用INFO命令監控Redis效能資料,如命令支援、記憶體使用等,及時調優。

比如,使用命令獲取監控資訊:

INFO memory
INFO clients

10. 避免熱點key

熱點key會造成單一節點的壓力,透過隨機化訪問來避免。

比如,可以為熱點key加隨機字尾:

String key = "hotkey:" + (System.currentTimeMillis() % 10);
jedis.incr(key);

11. 使用壓縮

儲存大物件時,考慮使用壓縮技術來節省記憶體。

比如,可以使用GZIP壓縮JSON資料:

byte[] compressed = gzipCompress(jsonString);
jedis.set("data", compressed);

12. 使用Geo位置功能

Redis支援地理位置儲存和查詢,使用GEOADD可以高效管理地理資料。

比如,儲存地點資訊:

jedis.geoadd("locations", longitude, latitude, "LocationName");

13. 控制資料的持久化

合理設定RDBAOF的持久化策略,避免頻繁寫盤造成效能下降。

示例:
設定持久化的時間間隔:

save 900 1
appendonly yes

14. 儘量減少事務使用

在高併發場景下,避免過度使用MULTI/EXEC,因為事務會鎖住key。

可以直接使用單條命令替代事務。

15. 合理配置客戶端

調整客戶端的連線超時和重連策略,以適應高負載場景,確保連線穩定。

例如:

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128); // 最大連線數
poolConfig.setMaxIdle(64); // 最大空閒連線
poolConfig.setMinIdle(16); // 最小空閒連線
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);

JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379, 2000); // 連線超時2000ms

16. 使用Redis Sentinel

使用Sentinel進行監控,實現高可用性,確保系統在故障時能夠快速切換。

配置Sentinel進行主從複製。

17. 最佳化網路配置

保證Redis伺服器有良好的網路頻寬,避免網路瓶頸。

使用伺服器內部專線,減少延遲。

18. 定期清理不必要的資料

生命週期管理很關鍵,定期刪除過期或不必要的資料,保持記憶體高效利用。

可以設定Cron任務定期清理。

雖說Redis內部會清理過期的資料,但有些長期存在的垃圾資料,也建議及時清理。

總結

以上就是Redis效能最佳化的18條軍規,靈活應用這些策略能夠為你的專案帶來顯著的效能提升。希望能幫助到你,歡迎分享你的最佳化經驗!

最後說一句(求關注,別白嫖我)

如果這篇文章對您有所幫助,或者有所啟發的話,幫忙掃描下發二維碼關注一下,您的支援是我堅持寫作最大的動力。
求一鍵三連:點贊、轉發、在看。
關注公眾號:【蘇三說技術】,在公眾號中回覆:進大廠,可以免費獲取我最近整理的10萬字的面試寶典,好多小夥伴靠這個寶典拿到了多家大廠的offer。

相關文章