Redis帮助类

using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp7
{
    public class RedisHelper
    {
        public static readonly RedisHelper Instance = new RedisHelper();

        private readonly object _syncRoot = new object();

        /// <summary>
        /// redis分布式锁
        /// </summary>
        private Redlock.CSharp.Redlock dlm_redlock { get; set; }
        private RedisHelper()
        {

        }

        public ConnectionMultiplexer RedisConnectionManager
        {
            get; private set;
        }

        private IDatabase _redisDatabase;

        public IDatabase RedisDatabase
        {
            get
            {
                return this._redisDatabase;
            }
            set
            {
                this._redisDatabase = value;
            }
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="configuration"></param>
        public void Init(string configuration)
        {
            try
            {
                RedisConnectionManager = ConnectionMultiplexer
                    .Connect(configuration);
                RedisDatabase = this.RedisConnectionManager.GetDatabase();

                List<ConnectionMultiplexer> listCM = new List<ConnectionMultiplexer>();
                foreach (var item in configuration.Split(','))
                {
                    listCM.Add(ConnectionMultiplexer.Connect(item));
                }
                dlm_redlock = new Redlock.CSharp.Redlock(listCM[0]);
            }
            catch (Exception ex)
            {
               // LogHelper.WriteLog(ex.Message, ex);
                throw ex;
            }
        }
        /// <summary>
        /// 反初始化
        /// </summary>
        public void UnInit()
        {
            RedisDatabase = null;
            if (RedisConnectionManager != null)
                RedisConnectionManager.Dispose();
        }

        public void HashIncrement(string mapName, string key)
        {
            RedisDatabase.HashIncrement(mapName, key);
        }

        //public void StringIncrement(string key)
        //{
        //    RedisDatabase.StringIncrement(key);
        //}

        /// <summary>
        /// 以分布式锁的方式读取写入值到redis
        /// </summary>
        /// <param name="lockKey">锁定资源的key</param>
        /// <param name="action">具体操作</param>
        /// <param name="throwExecption">未获取到分布式锁是否抛出异常默认为是</param>
        public void LockAction(string lockKey, Action<IDatabase> action, bool throwExecption = true)
        {
            if (action == null)
            {
                throw new ArgumentNullException("参数action空异常");
            }
            Redlock.CSharp.Lock lockObject;
            var locked = GetLock(lockKey, out lockObject);
            //没有获取到锁 则进行等待,最多等待5秒
            int total = 0;
            Random rdm = new Random();
            int sleepTime = 0;
            while (!locked)
            {
                sleepTime = rdm.Next(100, 200);
                //等待100毫秒,重新获取
                Thread.Sleep(sleepTime);
                total += sleepTime;
                locked = GetLock(lockKey, out lockObject);
                if (total > 11000)
                {
                    break;
                }
            }
            if (!locked && throwExecption)
            {
                throw new Exception("获取redis分布式锁失败");
            }
            if (locked)
            {
                try
                {
                    action(RedisDatabase);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    //释放分布式锁
                    dlm_redlock.Unlock(lockObject);
                }
            }
        }
        /// <summary>
        /// 获取分布式锁
        /// </summary>
        /// <param name="lockKey"></param>
        /// <param name="lockObject">锁对象</param>
        /// <returns>获取锁是否成功</returns>
        private bool GetLock(string lockKey, out Redlock.CSharp.Lock lockObject)
        {
            return dlm_redlock.Lock(
                  "RedLock_" + lockKey,
                  new TimeSpan(0, 0, 10),//最多锁10s 则自动释放锁
                  out lockObject
              );
        }

        public void HSet(string mapName, string key, string value)
        {
            lock (this._syncRoot)
            {
                //this.RedisClient.HSet(mapName, GetBytes(key), GetBytes(value));
                this.RedisDatabase.HashSet(mapName, key, value);
            }
        }

        public string HGet(string mapName, string key)
        {
            lock (this._syncRoot)
            {
                //byte[] value = this.RedisClient.HGet(mapName, GetBytes(key));
                //if (value == null || value.Length == 0)
                //{
                //    return null;
                //}
                //string str = GetString(value);
                //return str;
                string str = this.RedisDatabase.HashGet(mapName, key);
                return str;
            }
        }

        public IDictionary<string, string> HGetAll(string mapName)
        {
            lock (this._syncRoot)
            {
                //byte[][] values = this.RedisClient.HGetAll(mapName);
                //int count = values.Length / 2;
                //IDictionary<string, string> dic = new Dictionary<string, string>(count);
                //for (int i = 0; i < values.Length;)
                //{
                //    string key = GetString(values[i++]);
                //    string value = GetString(values[i++]);
                //    dic[key] = value;
                //}

                //return dic;
                HashEntry[] entries = this.RedisDatabase.HashGetAll(mapName);
                IDictionary<string, string> dic = new Dictionary<string, string>();
                for (int i = 0; i < entries.Length; i++)
                {
                    HashEntry entry = entries[i];
                    string key = entry.Name;
                    string value = entry.Value;
                    dic[key] = value;
                }

                return dic;
            }
        }

        //private readonly Random _radom = new Random();

        public IDictionary<string, string> HScan(string mapName, string pattern, int size)
        {
            lock (this._syncRoot)
            {
                IEnumerable<HashEntry> entries = this.RedisDatabase.HashScan(
                    mapName, pattern, 10, CommandFlags.None);
                if (entries == null)
                {
                    throw new ApplicationException("HSCAN 命令出错,返回空");
                }
                IDictionary<string, string> dic = new Dictionary<string, string>();
                foreach (HashEntry entry in entries)
                {
                    string key = entry.Name;
                    string value = entry.Value;
                    dic[key] = value;
                    if (--size <= 0)
                    {
                        break;
                    }
                }

                return dic;
            }
        }

        public int Del(string key)
        {
            lock (this._syncRoot)
            {
                //int value = this.RedisClient.HDel(mapName, GetBytes(key));
                bool flag = this.RedisDatabase.KeyDelete(key);
                return flag ? 1 : 0;
            }
        }

        public void StringSet(string key, string value, TimeSpan? expiry = null)
        {
            lock (this._syncRoot)
            {
                //int value = this.RedisClient.HDel(mapName, GetBytes(key));
                this.RedisDatabase.StringSet(key, value, expiry);
                return;
            }
        }

        public string StringGet(string key)
        {
            lock (this._syncRoot)
            {
                //int value = this.RedisClient.HDel(mapName, GetBytes(key));
                RedisValue value = this.RedisDatabase.StringGet(key);
                string sv = (string)value;
                return sv;
            }
        }

        public int HDel(string mapName, string key)
        {
            lock (this._syncRoot)
            {
                //int value = this.RedisClient.HDel(mapName, GetBytes(key));
                bool flag = this.RedisDatabase.HashDelete(mapName, key);
                return flag ? 1 : 0;
            }
        }

        public void SAdd(string setName, string value)
        {
            lock (this._syncRoot)
            {
                bool flag = this.RedisDatabase.SetAdd(setName, value);
            }
        }

        public long SAdd(string setName, IList<string> values)
        {
            lock (this._syncRoot)
            {
                RedisValue[] rvs = values.Select(p => (RedisValue)p).ToArray();
                long count = this.RedisDatabase.SetAdd(setName, rvs);
                return count;
            }
        }

        public IList<string> SIntersect(IList<string> setNames)
        {
            lock (this._syncRoot)
            {
                RedisKey[] keys = setNames.Select(p => (RedisKey)(p)).ToArray();
                RedisValue[] values = this.RedisDatabase.SetCombine(SetOperation.Intersect, keys);
                IList<string> list = values.Select(p => (string)p).ToList();
                return list;
            }
        }

        public IList<string> SScan(string sname, string pattern, int offset, int count)
        {
            IList<string> list = new List<string>();
            lock (this._syncRoot)
            {
                IEnumerable<RedisValue> iter = this.RedisDatabase.SetScan(sname, pattern, 10);
                foreach (var item in iter)
                {
                    if (offset > 0)
                    {
                        --offset;
                        continue;
                    }
                    if (count > 0)
                    {
                        --count;
                        list.Add((string)item);
                    }
                }
            }
            return list;
        }

        public long SCard(string setName)
        {
            long result = this.RedisDatabase.SetLength(setName);
            return result;
        }

        public bool KeyExpire(string key, TimeSpan? ts)
        {
            lock (this._syncRoot)
            {
                bool flag = this.RedisDatabase.KeyExpire(key, ts);
                return flag;
            }
        }

        public bool KeyExists(string key)
        {
            lock (this._syncRoot)
            {
                bool flag = this.RedisDatabase.KeyExists(key);
                return flag;
            }
        }

        public string HGet(string assetsStatusMap)
        {
            throw new NotImplementedException();
        }

        //private string GetString(byte[] bytes)
        //{
        //    return _encoding.GetString(bytes);
        //}

        //private byte[] GetBytes(string str)
        //{
        //    return _encoding.GetBytes(str);
        //}

        public long LPush(string key, string value)
        {
            lock (this._syncRoot)
            {
                return this.RedisDatabase.ListLeftPush(key, value);
            }
        }

        public long RPush(string key, string value)
        {
            lock (this._syncRoot)
            {
                return this.RedisDatabase.ListRightPush(key, value);
            }
        }

        public string[] LRange(string key, long start, long stop)
        {
            lock (this._syncRoot)
            {
                var vals = this.RedisDatabase.ListRange(key, start, stop);
                return vals.Select(p => (string)p).ToArray();
            }
        }

        public void LRemove(string key, string value, int count)
        {
            lock (this._syncRoot)
            {
                this.RedisDatabase.ListRemove(key, value, count);
            }
        }
    }
}

具体调用详解

 1、存入map类型数据(只能一次存入,第二次在执行存入相同Redis键值时新值不能存入)

 class Program
    {     
        static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "9526";
            if (!redis.KeyExists(KEY))
            {
                redis.HSet(KEY, "77", "55");
                redis.HSet(KEY, "77", "55");
                redis.HSet(KEY, "88", "66");
            }
            var a = redis.HGet(KEY, "77");//获取值 55
            var b = redis.Del(KEY);//返回1表示删除成功--根据redis键值删除
            var c = redis.HDel(KEY, "77"); //根据redis键值和存入数据的key删除指定的值
        }
      
    }

 存入

 

 根据redis的key与值中的key删除

 

2、存入list(可循环调用存入)

static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "9527";
          //  List<string> listCode = new List<string>() { "111", "2222" };//第一次存入
            List<string> listCode = new List<string>() { "333", "2222" };//第二次存入
            RedisHelper.Instance.SAdd(KEY, listCode);
            var b = redis.Del(KEY);//返回1表示删除成功--根据redis键值删除
        }

 

3、业务场景:用作计算次数

static void Main(string[] args)
{
RedisHelper redis = null;
redis = RedisHelper.Instance;
string RedisServer = "127.0.0.1:6379";
redis.Init(RedisServer);
string key = DateTime.Now.ToString("yyyy-MM-dd");
redis.HashIncrement("Test", key + "_" + "24");
redis.HashIncrement("Test", key + "_" + "24"); 
}

 

4、HGetAll

 IDictionary<string, string> dicInfo = redis.HGetAll("9526");
            foreach (string item in dicInfo.Keys)
            {
               
               
            }

 5、设置redis的key时效

  static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "999";
            if (!redis.KeyExists(KEY))
            {
                redis.HSet(KEY, "11", "55");
               
            }
            var a = redis.HGet(KEY, "77");//获取值 55
            TimeSpan sp = new TimeSpan(0, 2, 0);//设置key值的时效为2分钟,2分钟后会自动删除redis里key及数据
            RedisHelper.Instance.KeyExpire(KEY, sp);
        }

 6、leftPush和rightPush

redis对list操作分为左和右两种
lPush将数据添加到key对应的现有数据的左边,也就是头部,rPush是将现有数据添加到现有数据的右边,也就是尾部,可以根据业务的不同进行对应的添加

 static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            //string KEY = "RPush";
            //RedisHelper.Instance.RPush(KEY, "914");//每次新增的数据都在尾部
            //RedisHelper.Instance.RPush(KEY, "915");
            //RedisHelper.Instance.RPush(KEY, "916");
            string KEY = "LPush";
            RedisHelper.Instance.LPush(KEY, "914");//每次新增的数据都在头部
            RedisHelper.Instance.LPush(KEY, "915");
            RedisHelper.Instance.LPush(KEY, "916");

        }

 

 

 7、key值分组

static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);           
            string KEY = "Test:11";
            redis.LPush(KEY, "911");
            string KEY2 = "Test:22";
            redis.LPush(KEY2, "911");       
        }

 8、ListRange使用(根据key值以及list的值删除)

 static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "LPush";
            // Redis Lrange 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 
            //其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,
            //以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
            string[] vals = RedisHelper.Instance.LRange(KEY, 0, -1);//916,915,914
            string[] vals2 = RedisHelper.Instance.LRange(KEY, 1, -1);//915,914
            string[] vals3 = RedisHelper.Instance.LRange(KEY, 1, -2);//915
            string[] vals4 = RedisHelper.Instance.LRange(KEY, 2, -1);//914

        }

 9、ListRemove

 static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "LPush";
            RedisHelper.Instance.LRemove(KEY, "916", 1); //删除916这条数据       
        }

 

10、redis分页查询

Redis中有一个经典的问题,在巨大的数据量的情况下,做类似于查找符合某种规则的Key的信息,这里就有两种方式,
一是keys命令,简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代价越大,产生的阻塞时间越长。
二是scan命令,以非阻塞的方式实现key值的查找,绝大多数情况下是可以替代keys命令的,可选性更强

  static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            string KEY = "955";
            List<string> list = new List<string>() { "", "3", "2", "1" };
            redis.SAdd(KEY, list);
            int PageIndex = 0;
            int PageSize = 10;
            //分页查询
            IList<string> values = RedisHelper.Instance.SScan(
               KEY,
               "*",
               PageIndex * PageSize,
               PageSize);
            long count = RedisHelper.Instance.SCard(KEY);//总条数   
        }

 11、分布式锁

 /// <summary>
        /// redis锁定key
        /// </summary>
        private static string LOCK_KEY = "FavoriteFunctionTask";

        /// <summary>
        /// redis排它锁key
        /// </summary>
        private static string EXCLUSIVE_LOCK = LOCK_KEY + "_LOCK";
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            RedisHelper redis = null;
            redis = RedisHelper.Instance;
            string RedisServer = "127.0.0.1:6379";
            redis.Init(RedisServer);
            RedisHelper.Instance.LockAction(LOCK_KEY, db =>
            {
                //设置5分钟过时key
                if (string.IsNullOrEmpty(RedisHelper.Instance.StringGet(EXCLUSIVE_LOCK)))
                {
                    RedisHelper.Instance.StringSet(EXCLUSIVE_LOCK, "1", TimeSpan.FromMinutes(10));
                }
            }, false);
        }

 https://blog.csdn.net/weixin_34377919/article/details/88612882

posted on 2019-12-10 11:13  红磨坊后的白桦树  阅读(446)  评论(0编辑  收藏  举报