121 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
	
	
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;
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 |