第 4 篇:Redis 緩存與分布式鎖實現
一、Redis 在系統中的核心作用
-
票證信息緩存:將高頻訪問的票證數據(如狀態、有效期)緩存至 Redis,減少數據庫查詢,提升驗證響應速度。
-
分布式鎖:在高并發場景下,防止同一張票被同時驗證,確保 “一票一次” 機制的可靠性。
-
閘機狀態緩存:實時存儲閘機開關狀態,便于前端監控與管理。
二、Redis 集成步驟
- 安裝 StackExchange.Redis:
dotnet add package StackExchange.Redis
- 注冊 Redis 服務:在 Program.cs 中配置連接:
builder.Services.AddSingleton\<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(builder.Configuration.GetConnectionString("Redis")));
- 封裝 Redis 操作工具類:
public class RedisHelper{private readonly IDatabase _db;public RedisHelper(IConnectionMultiplexer redis){_db = redis.GetDatabase();}// 設置緩存(帶過期時間)public async Task SetAsync(string key, string value, TimeSpan? expiry = null){await _db.StringSetAsync(key, value, expiry);}// 獲取緩存public async Task<string> GetAsync(string key){return await _db.StringGetAsync(key);}}
三、分布式鎖實現
分布式鎖核心特性
- 互斥性:同一時間只有一個節點能獲取鎖。
- 安全性:避免死鎖(鎖必須有過期時間),不能誤刪他人的鎖。
- 可用性:Redis 故障時仍能基本可用(如主從切換)。
- 重入性:同一線程可重復獲取鎖(可選,視場景而定)。
public class RedisDistributedLock{private readonly IDatabase _db;private readonly string _lockPrefix = "lock:";public RedisDistributedLock(IConnectionMultiplexer redis){_db = redis.GetDatabase();}// 獲取鎖(返回鎖標識,用于釋放)public async Task<string> AcquireLockAsync(string resource, TimeSpan expiry){var lockKey = _lockPrefix + resource;var lockValue = Guid.NewGuid().ToString(); // 唯一標識,防止誤釋放// SET NX(不存在則設置)+ PX(過期時間)var acquired = await _db.StringSetAsync(lockKey, lockValue, expiry, When.NotExists);return acquired ? lockValue : null;}// 釋放鎖(Lua腳本保證原子性)public async Task ReleaseLockAsync(string resource, string lockValue){var lockKey = _lockPrefix + resource;var script = @"if redis.call('get', KEYS\[1]) == ARGV\[1] thenreturn redis.call('del', KEYS\[1])elsereturn 0end";await _db.ScriptEvaluateAsync(script, new RedisKey\[] { lockKey },new RedisValue[] { lockValue });}}
c
-
緩存更新:票證狀態變更(如使用后)時,同步更新 Redis 緩存。
-
過期時間:票證緩存設置與票證有效期關聯,避免緩存冗余。
-
緩存穿透防護:對不存在的票證,緩存空值(短期過期),減少無效數據庫查詢。
五、緩存常見問題
問題 | 描述 | 解決方案 |
---|---|---|
緩存穿透 | 查詢不存在的數據,穿透到DB | 1. 緩存空值(短期過期);2. 布隆過濾器預過濾不存在的key |
緩存擊穿 | 熱點key過期瞬間大量請求DB | 1. 互斥鎖(查詢時加鎖,只讓一個線程更新緩存);2. 熱點key永不過期 |
緩存雪崩 | 大量key同時過期,請求壓垮DB | 1. 過期時間加隨機值(分散過期);2. 服務熔斷/降級;3. 緩存集群高可用 |
六、注意事項
-
Redis 部署方式:
- 單機部署:鎖性能高,但存在單點故障風險。
- 主從+哨兵:提高可用性,但主從切換時可能出現“鎖丟失”(可通過 Redisson 的 RedLock 算法緩解,但性能有損耗)。
-
鎖超時處理:
- 鎖過期時間需大于業務執行時間,避免業務未完成鎖已釋放。
- 可使用“鎖續期”機制(如 Redisson 的 Watch Dog),自動延長鎖有效期。
-
緩存與鎖的結合:
- 緩存更新時需加鎖避免并發問題(如緩存擊穿場景)。
- 分布式鎖的粒度應盡量小,避免影響性能。
總結
- Redis 緩存:通過合理的緩存策略(如 Cache-Aside)和問題解決方案,可顯著提升系統性能。
- 分布式鎖:基于 Redis 的
SET NX PX
命令可實現基礎鎖,生產環境推薦使用 Redisson 簡化開發并避免潛在問題。
兩者結合可有效解決分布式系統中的性能與并發安全問題。