wanshenmean
2026-03-04 17e5dbd7bd0364e27a33f1a7dab91cf33d5dcabc
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/RedisʹÓð¸Àý.md
@@ -1,6 +1,6 @@
# Redis æœåŠ¡ä½¿ç”¨æ¡ˆä¾‹
## 1. ç¼“存(ICacheService)
## 1. ç¼“存(ICacheService)- åŸºç¡€æ“ä½œ
通过构造函数注入 `ICacheService`,HybridCacheService è‡ªåŠ¨å®žçŽ° L1(内存) + L2(Redis) åŒå±‚缓存。
@@ -38,7 +38,211 @@
}
```
## 2. åˆ†å¸ƒå¼é”ï¼ˆIDistributedLockService)
## 2. ç¼“存(ICacheService)- æ‰©å±•删除方法
```csharp
public class CacheDeleteDemo
{
    private readonly ICacheService _cache;
    // åˆ é™¤å¹¶èŽ·å–å€¼
    public string? RemoveAndGet(string key)
    {
        return _cache.RemoveAndGet(key); // è¿”回被删除的值
    }
    // æŒ‰å‰ç¼€åˆ é™¤æ‰€æœ‰åŒ¹é…çš„key
    public int ClearUserCache()
    {
        return _cache.RemoveByPrefix("user:"); // åˆ é™¤æ‰€æœ‰ user: å¼€å¤´çš„key
    }
    // æŒ‰æ¨¡å¼åˆ é™¤ï¼ˆæ”¯æŒé€šé…ç¬¦ï¼‰
    public int ClearSessionCache()
    {
        return _cache.RemoveByPattern("session:123:*"); // åˆ é™¤ session:123: å¼€å¤´çš„æ‰€æœ‰key
    }
    // æ‰¹é‡åˆ é™¤å¹¶è¿”回成功数量
    public int RemoveMultiple()
    {
        var keys = new[] { "key1", "key2", "key3" };
        return _cache.RemoveAll(keys); // è¿”回实际删除的数量
    }
    // æ¡ä»¶åˆ é™¤
    public int RemoveTempCache()
    {
        return _cache.RemoveWhere(key => key.Contains("temp")); // åˆ é™¤åŒ…含"temp"的key
    }
}
```
## 3. ç¼“存(ICacheService)- æ·»åŠ å’Œä¿®æ”¹æ‰©å±•æ–¹æ³•
```csharp
public class CacheAdvancedDemo
{
    private readonly ICacheService _cache;
    // æ‰¹é‡æ·»åŠ 
    public void AddMultiple()
    {
        var items = new Dictionary<string, string>
        {
            { "user:1", "张三" },
            { "user:2", "李四" },
            { "user:3", "王五" }
        };
        _cache.AddAll(items, 300); // æ‰¹é‡æ·»åŠ ï¼Œ300秒过期
    }
    // æ‰¹é‡æ·»åŠ å¯¹è±¡
    public void AddMultipleObjects()
    {
        var items = new Dictionary<string, object>
        {
            { "order:1", new { Id = 1, Amount = 100 } },
            { "order:2", new { Id = 2, Amount = 200 } }
        };
        _cache.AddAllObjects(items, 600);
    }
    // æ›¿æ¢ï¼ˆä»…存在时替换)
    public bool ReplaceExisting()
    {
        return _cache.Replace("user:1", "新用户名"); // key不存在返回false
    }
    // èŽ·å–å¹¶åˆ·æ–°è¿‡æœŸæ—¶é—´
    public string? GetAndRefresh(string key)
    {
        return _cache.GetAndRefresh(key, 1800); // èŽ·å–å€¼å¹¶å»¶é•¿30分钟
    }
    // åˆ·æ–°è¿‡æœŸæ—¶é—´
    public bool RefreshExpire(string key)
    {
        return _cache.RefreshExpire(key, 3600); // åˆ·æ–°ä¸º1小时后过期
    }
    // è®¾ç½®N秒后过期
    public bool SetExpireIn(string key, int seconds)
    {
        return _cache.ExpireIn(key, seconds);
    }
    // è®¾ç½®åœ¨æŒ‡å®šæ—¶é—´ç‚¹è¿‡æœŸ
    public bool SetExpireAt(string key, DateTime expireTime)
    {
        return _cache.ExpireAt(key, expireTime);
    }
    // èŽ·å–å‰©ä½™è¿‡æœŸæ—¶é—´
    public long? GetTTL(string key)
    {
        return _cache.GetExpire(key); // è¿”回剩余秒数,null表示永不过期或key不存在
    }
}
```
## 4. ç¼“存(ICacheService)- åŽŸå­æ“ä½œæ–¹æ³•
```csharp
public class AtomicOperationDemo
{
    private readonly ICacheService _cache;
    // åŽŸå­æ·»åŠ ï¼ˆä»…ä¸å­˜åœ¨æ—¶æ·»åŠ ï¼‰- åˆ†å¸ƒå¼é”åœºæ™¯
    public bool AcquireLock(string lockKey, string lockValue)
    {
        return _cache.AddIfNotExists(lockKey, lockValue, 30); // 30秒自动过期
    }
    // èŽ·å–æ—§å€¼å¹¶è®¾ç½®æ–°å€¼
    public string? GetAndSet(string key, string newValue)
    {
        return _cache.GetAndSet(key, newValue); // è¿”回旧值,设置新值
    }
    // è‡ªå¢žè®¡æ•°å™¨
    public long IncrementCounter(string key)
    {
        return _cache.Increment(key); // è‡ªå¢ž1,返回新值
    }
    // è‡ªå¢žæŒ‡å®šå€¼
    public long IncrementBy(string key, long value)
    {
        return _cache.Increment(key, value); // è‡ªå¢žvalue
    }
    // è‡ªå‡è®¡æ•°å™¨
    public long DecrementCounter(string key)
    {
        return _cache.Decrement(key); // è‡ªå‡1
    }
    // è¿½åР内容
    public long AppendContent(string key, string content)
    {
        return _cache.Append(key, content); // è¿”回追加后的字符串长度
    }
}
```
## 5. ç¼“存(ICacheService)- ConcurrentDictionary风格方法
```csharp
public class ConcurrentStyleDemo
{
    private readonly ICacheService _cache;
    // å°è¯•添加(仅不存在时添加)
    public bool TryAdd(string key, string value)
    {
        return _cache.TryAdd(key, value, 60); // key存在返回false
    }
    // å°è¯•获取
    public bool TryGet(string key, out string? value)
    {
        return _cache.TryGetValue(key, out value);
    }
    // å°è¯•移除并返回值
    public bool TryRemove(string key, out string? value)
    {
        return _cache.TryRemove(key, out value);
    }
    // å°è¯•更新(仅存在时更新)
    public bool TryUpdate(string key, string newValue)
    {
        return _cache.TryUpdate(key, newValue, 60);
    }
    // å€¼æ”¹å˜æ—¶æ›´æ–°ï¼ˆé¿å…æ— æ•ˆå†™å…¥ï¼‰
    public bool TryUpdateIfChanged(string key, string newValue)
    {
        return _cache.TryUpdateIfChanged(key, newValue, 60); // å€¼ç›¸åŒè¿”回false
    }
    // èŽ·å–æˆ–æ·»åŠ 
    public string GetOrAdd(string key)
    {
        return _cache.GetOrAdd(key, "默认值", 60);
    }
    // èŽ·å–æˆ–æ·»åŠ ï¼ˆå·¥åŽ‚æ–¹æ³•ï¼‰
    public T GetOrAdd<T>(string key, Func<string, T> factory) where T : class
    {
        return _cache.GetOrAdd(key, factory, 60);
    }
}
```
## 6. åˆ†å¸ƒå¼é”ï¼ˆIDistributedLockService)
```csharp
public class OrderService
@@ -80,7 +284,7 @@
}
```
## 3. è®¡æ•°å™¨ï¼ˆICounterService)
## 7. è®¡æ•°å™¨ï¼ˆICounterService)
```csharp
public class StatisticsService
@@ -107,7 +311,7 @@
}
```
## 4. å‘布/订阅(IMessageQueueService)
## 8. å‘布/订阅(IMessageQueueService)
```csharp
public class NotificationService
@@ -143,7 +347,7 @@
}
```
## 5. é™æµï¼ˆIRateLimitingService)
## 9. é™æµï¼ˆIRateLimitingService)
```csharp
public class ApiController
@@ -175,7 +379,7 @@
}
```
## 6. åˆ†å¸ƒå¼ID生成器(IDistributedIdGenerator)
## 10. åˆ†å¸ƒå¼ID生成器(IDistributedIdGenerator)
```csharp
public class TaskService
@@ -203,7 +407,7 @@
}
```
## 7. æŽ’行榜(ILeaderboardService)
## 11. æŽ’行榜(ILeaderboardService)
```csharp
public class LeaderboardDemo
@@ -231,7 +435,7 @@
}
```
## 8. å¯¹è±¡å­˜å‚¨ï¼ˆIObjectStorageService)
## 12. å¯¹è±¡å­˜å‚¨ï¼ˆIObjectStorageService)
```csharp
public class DeviceService
@@ -259,7 +463,7 @@
}
```
## 9. é…ç½®ä¸­å¿ƒï¼ˆIConfigurationCenterService)
## 13. é…ç½®ä¸­å¿ƒï¼ˆIConfigurationCenterService)
```csharp
public class ConfigDemo
@@ -290,7 +494,7 @@
}
```
## 10. ç›‘控(IRedisMonitorService)
## 14. ç›‘控(IRedisMonitorService)
```csharp
public class MonitorDemo
@@ -318,7 +522,7 @@
}
```
## 11. Session存储(ISessionStorage)
## 15. Session存储(ISessionStorage)
```csharp
public class SessionDemo
@@ -350,7 +554,7 @@
}
```
## 12. å¸ƒéš†è¿‡æ»¤å™¨ï¼ˆIBloomFilterService)
## 16. å¸ƒéš†è¿‡æ»¤å™¨ï¼ˆIBloomFilterService)
```csharp
public class BloomFilterDemo
@@ -378,3 +582,45 @@
    }
}
```
## 17. ç¼“存自动同步(CacheSyncBackgroundService)
Redis到内存缓存的自动同步后台服务,解决L1+L2混合缓存中外部修改Redis数据导致内存缓存不一致的问题。
### é…ç½®è¯´æ˜Ž
在 `appsettings.json` ä¸­é…ç½®ï¼š
```json
{
  "RedisConfig": {
    "EnableL1Cache": true,           // å¯ç”¨L1内存缓存
    "EnableAutoSync": true,          // å¯ç”¨è‡ªåŠ¨åŒæ­¥
    "SyncIntervalSeconds": 30,       // åŒæ­¥é—´éš”:30秒
    "SyncBatchSize": 1000            // å•次批量获取key数量上限
  }
}
```
### å·¥ä½œåŽŸç†
1. **启动时全量同步**:服务启动后立即执行一次全量同步
2. **定期增量同步**:按照配置的间隔(默认30秒)定期执行同步
3. **双向同步**:
   - å°†Redis中的数据更新到内存缓存
   - æ¸…理内存缓存中不存在于Redis的key
4. **智能TTL同步**:同步时会保留Redis中设置的过期时间
### ä½¿ç”¨åœºæ™¯
- **多系统共享Redis**:当多个WCS实例共享同一个Redis,一个实例修改数据后,其他实例能自动同步
- **外部修改Redis**:通过Redis CLI或其他工具修改数据后,应用能自动获取最新值
- **缓存一致性保障**:避免启用L1缓存后,内存缓存和Redis数据不一致的问题
### æ³¨æ„äº‹é¡¹
- ä»…在 `EnableL1Cache = true` ä¸” `EnableAutoSync = true` æ—¶è¿è¡Œ
- IMemoryCache不支持枚举,因此只能清理已跟踪的key
- åŒæ­¥é—´éš”建议设置为30-60秒,过短会影响性能
- å¯¹äºŽè¦æ±‚强一致性的场景,建议直接禁用L1缓存(`EnableL1Cache: false`)
```