Redis 性能優化 18 招

前言

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

Redis 的使用場景也很多。

比如:保存用戶登錄態,做限流,做分佈式鎖,做緩存提升數據訪問速度等等。

那麼問題來了,Redis 的性能要如何優化?

爲了提升 Redis 的性能,這篇文章跟大家一起聊聊 Redis 性能優化的 18 招,希望對你會有所幫助。

  1. 選擇合適的數據結構

Redis 支持多種數據結構,如字符串、哈希、列表、集合和有序集合。根據實際需求選擇合適的數據結構可以提高性能。

如果要存儲用戶信息,考慮使用哈希而不是多個字符串:

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

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

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

較長的 key 和 value 會佔用更多內存,還可能影響性能。

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

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

還可以做壓縮等其他優化。

  1. 使用 Redis Pipeline

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

比如,批量設置 key 可以這樣做:

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

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

  1. 控制連接數量

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

比如,使用 JedisPool:

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

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

能有效的節省連接的創建和銷燬時間。

  1. 合理使用過期策略

設置合理的過期策略,能防止內存被不再使用的數據佔滿。

例如,緩存熱點數據可以設置過期時間。

比如,對會話數據設置過期時間:

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

Redis 內部會定期清理過期的緩存。

  1. 使用 Redis 集羣

數據量增大時,使用 Redis 集羣可以將數據分散到多個節點,提升併發性能。

可以將數據哈希分片到多個 Redis 實例。

這樣可以避免單個 Redis 實例,數據太多,佔用內存過多的問題。

  1. 充分利用內存優化

選擇合適的內存管理策略,Redis 支持 LRU(Least Recently Used)策略,可以自動刪除不常用的數據。

比如,配置 Redis 的 maxmemory:

maxmemory 256mb
maxmemory-policy allkeys-lru
  1. 使用 Lua 腳本

Lua 腳本讓多條命令在 Redis 中原子性執行,減少網絡延遲。

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

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

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

  1. 監控與調優

使用 INFO 命令監控 Redis 性能數據,如命令支持、內存使用等,及時調優。

比如,使用命令獲取監控信息:

INFO memory
INFO clients
  1. 避免熱點 key

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

比如,可以爲熱點 key 加隨機後綴:

String key = "hotkey:" + (System.currentTimeMillis() % 10);
jedis.incr(key);
  1. 使用壓縮

存儲大對象時,考慮使用壓縮技術來節省內存。

比如,可以使用GZIP壓縮 JSON 數據:

byte[] compressed = gzipCompress(jsonString);
jedis.set("data", compressed);
  1. 使用 Geo 位置功能

Redis 支持地理位置存儲和查詢,使用GEOADD可以高效管理地理數據。

比如,存儲地點信息:

jedis.geoadd("locations", longitude, latitude, "LocationName");
  1. 控制數據的持久化

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

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

save 900 1
appendonly yes
  1. 儘量減少事務使用

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

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

  1. 合理配置客戶端

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

例如:

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
  1. 使用 Redis Sentinel

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

配置 Sentinel 進行主從複製。

  1. 優化網絡配置

保證 Redis 服務器有良好的網絡帶寬,避免網絡瓶頸。

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

  1. 定期清理不必要的數據

生命週期管理很關鍵,定期刪除過期或不必要的數據,保持內存高效利用。

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

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

總結

以上就是 Redis 性能優化的 18 招,靈活應用這些策略能夠爲你的項目帶來顯著的性能提升。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/znS0ogvjeMFTeD-NnIMTMA