2025-03-22 12:16:22 +00:00
|
|
|
|
using LY.App.Extensions.DI;
|
|
|
|
|
|
using StackExchange.Redis;
|
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
|
|
|
|
|
|
namespace LY.App.Common.Redis
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// redis 连接服务
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class RedisService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IDatabase _db;
|
2025-06-16 09:09:38 +00:00
|
|
|
|
private readonly IServer _redis;
|
2025-03-22 12:16:22 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构造函数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="connectionString"></param>
|
|
|
|
|
|
public RedisService(string connectionString)
|
|
|
|
|
|
{
|
|
|
|
|
|
var redis = ConnectionMultiplexer.Connect(connectionString);
|
|
|
|
|
|
_db = redis.GetDatabase();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 泛型存储数据到 Redis
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
string jsonData = JsonSerializer.Serialize(value);
|
|
|
|
|
|
return await _db.StringSetAsync(key, jsonData, expiry);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 泛型获取数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<T?> GetAsync<T>(string key)
|
|
|
|
|
|
{
|
|
|
|
|
|
string jsonData = await _db.StringGetAsync(key);
|
|
|
|
|
|
return jsonData is not null ? JsonSerializer.Deserialize<T>(jsonData) : default;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
2025-06-16 09:09:38 +00:00
|
|
|
|
/// 模糊 查询所有 Key
|
2025-03-22 12:16:22 +00:00
|
|
|
|
/// </summary>
|
2025-06-16 09:09:38 +00:00
|
|
|
|
/// <param name="pattern"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-16 09:15:19 +00:00
|
|
|
|
public Task<List<RedisKey>> GetAllKeysAsync(string pattern)
|
2025-03-22 12:16:22 +00:00
|
|
|
|
{
|
2025-06-16 09:09:38 +00:00
|
|
|
|
var redis = _db.Multiplexer;
|
|
|
|
|
|
var keys = new List<RedisKey>();
|
|
|
|
|
|
foreach (var endPoint in redis.GetEndPoints())
|
|
|
|
|
|
{
|
|
|
|
|
|
var server = redis.GetServer(endPoint);
|
2025-03-22 12:16:22 +00:00
|
|
|
|
|
2025-06-16 09:09:38 +00:00
|
|
|
|
if (!server.IsConnected)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 SCAN 获取匹配的 key,避免 KEYS 阻塞
|
|
|
|
|
|
var scanKeys = server.Keys(pattern: pattern, pageSize: 1000);
|
|
|
|
|
|
keys.AddRange(scanKeys);
|
|
|
|
|
|
}
|
2025-06-16 09:15:19 +00:00
|
|
|
|
return Task.FromResult(keys);
|
2025-06-16 09:09:38 +00:00
|
|
|
|
//var result = new Dictionary<string, string>();
|
|
|
|
|
|
|
|
|
|
|
|
//if (keys.Count > 0)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 一次批量获取 value
|
|
|
|
|
|
// var values = await _db.StringGetAsync(keys.ToArray());
|
|
|
|
|
|
|
|
|
|
|
|
// for (int i = 0; i < keys.Count; i++)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (values[i].HasValue)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// result[keys[i]] = values[i];
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//return result;
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
2025-06-16 09:09:38 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 删除 Key
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<bool> DeleteAsync(string key)
|
2025-03-26 03:23:39 +00:00
|
|
|
|
{
|
2025-06-16 09:09:38 +00:00
|
|
|
|
return await _db.KeyDeleteAsync(key);
|
2025-03-26 03:23:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-16 09:09:38 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查 Key 是否存在
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<bool> ExistsAsync(string key)
|
2025-03-26 03:23:39 +00:00
|
|
|
|
{
|
2025-06-16 09:09:38 +00:00
|
|
|
|
return await _db.KeyExistsAsync(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取数据,如果不存在则从数据源获取并存入 Redis
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T">数据类型</typeparam>
|
|
|
|
|
|
/// <param name="key">Redis Key</param>
|
|
|
|
|
|
/// <param name="factory">数据源方法</param>
|
|
|
|
|
|
/// <param name="expiry">可选的过期时间</param>
|
|
|
|
|
|
/// <returns>获取到的值</returns>
|
|
|
|
|
|
public async Task<T?> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var value = await GetAsync<T>(key);
|
|
|
|
|
|
if (value is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
value = await factory();
|
|
|
|
|
|
if (value is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
await SetAsync(key, value, expiry);
|
|
|
|
|
|
}
|
|
|
|
|
|
return value;
|
2025-03-26 03:23:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|