Loading

C# Redis简单封闭操作类

using StackExchange.Redis;
using System;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Common.Utils
{
    public class RedisUtils
    {

        #region redis连接地址

        /// <summary>
        /// redis连接地址
        /// </summary>
        private static string address = string.Empty;

        #region 读取连接地址
        private static string Address
        {
            get
            {
                if (address.IsNullOrEmpty())
                {
                    //读取参数
                    address = ConfigurationManager.AppSettings["redis_address"].ConvertStr();

                    //抛出异常
                    if (address.IsNullOrEmpty())
                    {
                        throw new ArgumentException("ConnectionAddress can not be null or empty.", nameof(address));
                    }
                }
                return address;
            }
        }
        #endregion 读取连接地址

        #endregion redis连接地址

        #region redis库

        /// <summary>
        /// redis连接地址
        /// </summary>
        private static int database = 0;

        #region 读取连接库地址
        private static int DataBase
        {
            get
            {
                if (database <= 0)
                {
                    //读取参数
                    database = ConfigurationManager.AppSettings["redis_database"].ConvertStr().ToInt32();

                    //抛出异常
                    if (database <= 0)
                    {
                        throw new ArgumentException("ConnectionDataBase can not be null or empty.", nameof(database));
                    }

                }
                return database;
            }
        }
        #endregion 读取连接库地址

        #endregion redis库

        #region redis连接端口号

        /// <summary>
        /// redis连接端口号
        /// </summary>
        private static int port = 0;

        #region 读取端口号
        private static int Port
        {
            get
            {
                if (port <= 0)
                {
                    //读取参数
                    port = ConfigurationManager.AppSettings["redis_port"].ConvertStr().ToInt32();

                    if (port <= 0)
                    {
                        throw new ArgumentException("ConnectionPort can not be null or empty.", nameof(port));
                    }
                }

                return port;
            }
        }
        #endregion 读取端口号

        #endregion redis连接端口号

        #region redis连接密码

        /// <summary>
        /// redis连接密码
        /// </summary>
        private static string password = string.Empty;

        #region 读取密码
        private static string Password
        {
            get
            {
                if (password.IsNullOrEmpty())
                {
                    //读取参数
                    return ConfigurationManager.AppSettings["redis_password"].ConvertStr();

                    if (password.IsNullOrEmpty())
                    {
                        throw new ArgumentException("ConnectionPassword can not be null or empty.", nameof(password));
                    }
                }

                return password;
            }
        }
        #endregion 读取密码

        #endregion redis连接密码

        #region redis前缀

        private static string _keyPrefix = string.Empty;

        /// <summary>
        /// Redis键值前缀
        /// </summary>
        private static string KeyPrefix
        {
            get
            {
                if (_keyPrefix.IsNullOrEmpty())
                {
                    _keyPrefix = ConfigurationManager.AppSettings["RedisKeyPrefix"].ConvertStr();
                    if (_keyPrefix.IsNullOrEmpty())
                        throw new ArgumentException("KeyPrefix can not be null or empty.", nameof(_keyPrefix));
                }

                return _keyPrefix;
            }
        }

        #endregion redis前缀

        private static ConnectionMultiplexer _redis;

        private static IDatabase _database;

        /// <summary>
        /// 初始化方法
        /// </summary>
        static RedisUtils()
        {
            var options = new ConfigurationOptions
            {
                EndPoints = { { Address, Port } },
                Password = Password,
                DefaultDatabase = DataBase
            };
            _redis = ConnectionMultiplexer.Connect(options);
            _database = _redis.GetDatabase(DataBase);
        }

        /// <summary>
        /// 标准化缓存名
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        protected static string StandardizeCacheKey(string cacheKey)
        {
            if (String.IsNullOrEmpty(cacheKey))
            {
                throw new ArgumentException("CacheKey can not be null or empty.", nameof(cacheKey));
            }
            return ($"{KeyPrefix}_{cacheKey}").ToLower();
        }

        /// <summary>
        /// 设置键值对
        /// </summary>
        /// <param name="key">redis key</param>
        /// <param name="value"></param>
        /// <param name="expiry">过期时间</param>
        public static async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = default, CancellationToken token = default)
        {

            key = StandardizeCacheKey(key);

            if (value == null)
                throw new ArgumentNullException("CacheValue can not be null or empty.", nameof(value));

            token.ThrowIfCancellationRequested();

            return await _database.StringSetAsync(key, RedisHelper.ConvertFromValue<T>(value), expiry);
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Get(string key)
        {
            return RedisHelper.ConvertToValue<string>(_database.StringGet(key));
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Get(string key, TimeSpan expiry)
        {
            key = StandardizeCacheKey(key);
            var redisVal = _database.StringGet(key);

            if (redisVal.IsNull)
                return null;

            if (expiry != null)
            {
                //滑动时间
                _database.KeyExpire(key, DateTime.Now.Add(expiry));
            }

            return redisVal;
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, CancellationToken token = default)
        {
            Log.Error("RedisUtil获取缓存方法被调用: key值为: " + key);

            key = StandardizeCacheKey(key);

            token.ThrowIfCancellationRequested();

            return RedisHelper.ConvertToValue<T>(await _database.StringGetAsync(key));
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, TimeSpan expiry, CancellationToken token = default)
        {
            key = StandardizeCacheKey(key);

            token.ThrowIfCancellationRequested();

            var redisVal = await _database.StringGetAsync(key);

            if (redisVal.IsNull)
                return default;

            if (expiry != null && expiry != TimeSpan.Zero)
            {
                //滑动时间
                await _database.KeyExpireAsync(key, expiry);
            }

            return RedisHelper.ConvertToValue<T>(redisVal);
        }

        /// <summary>
        /// 删除键
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Remove(string key)
        {
            key = StandardizeCacheKey(key);
            return _database.KeyDelete(key);
        }

        /// <summary>
        /// 删除键
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<bool> RemoveAsync(string key, CancellationToken token = default)
        {
            key = StandardizeCacheKey(key);

            token.ThrowIfCancellationRequested();

            return await _database.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 删除多个key
        /// </summary>
        /// <param name="keys">要删除的key集合</param>
        /// <returns>成功删除的个数</returns>
        public static long RemoveAll(params string[] keys)
        {
            RedisKey[] newkeys = keys.Select(o => (RedisKey)(StandardizeCacheKey(o))).ToArray();
            return _database.KeyDelete(newkeys);
        }

        /// <summary>
        /// 删除多个key
        /// </summary>
        /// <param name="keys">要删除的key集合</param>
        /// <returns>成功删除的个数</returns>
        public static async Task<long> RemoveAllAsync(CancellationToken token = default, params string[] keys)
        {
            RedisKey[] newkeys = keys.Select(o => (RedisKey)(StandardizeCacheKey(o))).ToArray();

            token.ThrowIfCancellationRequested();

            return await _database.KeyDeleteAsync(newkeys);
        }

        // 检查键是否存在
        public static bool KeyExists(string key)
        {
            key = StandardizeCacheKey(key);
            return _database.KeyExists(key);
        }

        // 检查键是否存在
        public static async Task<bool> KeyExistsASync(string key, CancellationToken token = default)
        {
            key = StandardizeCacheKey(key);

            token.ThrowIfCancellationRequested();

            return await _database.KeyExistsAsync(key);
        }

        // 设置键的过期时间
        public static bool SetExpiry(string key, TimeSpan expiry)
        {
            key = StandardizeCacheKey(key);
            return _database.KeyExpire(key, expiry);
        }

        // 设置键的过期时间
        public static async Task<bool> SetExpiryAsync(string key, TimeSpan? expiry = default, CancellationToken token = default)
        {
            key = StandardizeCacheKey(key);

            if (expiry == null || expiry == TimeSpan.Zero)
            {
                return false;
            }

            token.ThrowIfCancellationRequested();

            return await _database.KeyExpireAsync(key, expiry);
        }

        /// <summary>
        /// 清空当前DataBase中所有Key
        /// </summary>
        public static void KeyFulsh()
        {
            //直接执行清除命令
            _database.Execute("FLUSHDB");
        }
    }
}
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.Utils
{
    public static class RedisHelper
    {
        /// <summary>
        /// Redis值 转换到 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public static T ConvertToValue<T>(RedisValue redisValue)
        {
            var type = typeof(T);
            var compressMode = GetCompressMode(type);

            if (compressMode == CompressMode.None)
                return (T)Convert.ChangeType(redisValue, type);

            var byteValue = (byte[])redisValue;
            if (byteValue == null || byteValue.Length == 0)
                return default;

            var value = Decompress(byteValue);

            if (compressMode == CompressMode.Compress)
            {
                var valueString = Encoding.UTF8.GetString(value);
                return (dynamic)valueString;
            }

            string jsonString = Encoding.UTF8.GetString(value);
            var settings = new JsonSerializerSettings();
            settings.TypeNameHandling = TypeNameHandling.Auto;

            return JsonConvert.DeserializeObject<T>(jsonString, settings);
        }

        /// <summary>
        /// 对象 转换到 Redis值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static RedisValue ConvertFromValue<T>(T value)
        {
            var type = typeof(T);
            dynamic redisValue;
            switch (GetCompressMode(type))
            {
                case CompressMode.None:
                    redisValue = value;
                    break;
                case CompressMode.Compress:
                    redisValue = Compress(Encoding.UTF8.GetBytes(value?.ToString() ?? string.Empty));
                    break;
                default:
                    var settings = new JsonSerializerSettings();
                    settings.TypeNameHandling = TypeNameHandling.Auto;

                    var jsonString = JsonConvert.SerializeObject(value, settings);
                    redisValue = Compress(Encoding.UTF8.GetBytes(jsonString));
                    break;
            }
            return ConvertToRedisValue(type, redisValue);
        }

        /// <summary>
        /// 根据类型转换到 RedisValue
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static RedisValue ConvertToRedisValue(Type type, dynamic value)
        {
            if (type == typeof(byte) || type == typeof(ushort))
                return (long)value;

            if (type == typeof(decimal))
                return (double)value;

            return value;
        }

        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Compress(byte[] data)
        {
            using (MemoryStream msGZip = new MemoryStream())
            using (GZipStream stream = new GZipStream(msGZip, CompressionMode.Compress, true))
            {
                stream.Write(data, 0, data.Length);
                stream.Close();
                return msGZip.ToArray();
            }
        }

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Decompress(byte[] data)
        {
            using (MemoryStream ms = new MemoryStream(data))
            using (GZipStream stream = new GZipStream(ms, CompressionMode.Decompress))
            using (MemoryStream outBuffer = new MemoryStream())
            {
                byte[] block = new byte[1024];
                while (true)
                {
                    int bytesRead = stream.Read(block, 0, block.Length);
                    if (bytesRead <= 0)
                        break;
                    else
                        outBuffer.Write(block, 0, bytesRead);
                }
                return outBuffer.ToArray();
            }
        }

        /// <summary>
        /// 获得压缩类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static CompressMode GetCompressMode(this Type type)
        {
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.Double:
                case TypeCode.Single:
                case TypeCode.Decimal:
                    return CompressMode.None;
                case TypeCode.String:
                    return CompressMode.Compress;
                default:
                    return CompressMode.SerializeAndCompress;
            }
        }
    }

    /// <summary>
    /// 压缩模式
    /// </summary>
    internal enum CompressMode
    {
        /// <summary>
        /// 不压缩
        /// </summary>
        None = 1,

        /// <summary>
        /// 不序列化压缩
        /// </summary>
        Compress,

        /// <summary>
        /// 序列化并压缩
        /// </summary>
        SerializeAndCompress,
    }

}

 

posted @ 2024-04-03 10:42  jevan  阅读(28)  评论(0编辑  收藏  举报