ly/Common/Redis/RedisService.cs

121 lines
3.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
private readonly IServer _redis;
/// <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>
/// 模糊 查询所有 Key
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public Task<List<RedisKey>> GetAllKeysAsync(string pattern)
{
var redis = _db.Multiplexer;
var keys = new List<RedisKey>();
foreach (var endPoint in redis.GetEndPoints())
{
var server = redis.GetServer(endPoint);
if (!server.IsConnected)
continue;
// 使用 SCAN 获取匹配的 key避免 KEYS 阻塞
var scanKeys = server.Keys(pattern: pattern, pageSize: 1000);
keys.AddRange(scanKeys);
}
return Task.FromResult(keys);
//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;
}
/// <summary>
/// 删除 Key
/// </summary>
public async Task<bool> DeleteAsync(string key)
{
return await _db.KeyDeleteAsync(key);
}
/// <summary>
/// 检查 Key 是否存在
/// </summary>
public async Task<bool> ExistsAsync(string key)
{
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;
}
}
}