redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
主要用于数据存储(缓存)、发布订阅、消息队列以及分布式锁等。
1.redis安装 可以使用 window安装 还有 linux安装 以及docker安装
官网 https://redis.io/
中文 http://www.redis.cn/
2.可视化工具
RedisDesktopManager
3. c# 驱动
比较知名的c#驱动是 ServiceStack.Redis 和 StackExchange.Redis
由于ServiceStack.Redis,提供了默认的线程池是收费的,主要是需要付费解除并发数量的限制,
而StackExchange.Redis没有提供默认的线程池没有并发量的限制,是免费的。
StackExchange.Redis封装类 方便使用。
public class RedisManager { /// <summary> /// 锁对象 /// </summary> private static object _locker = new object(); /// <summary> /// StackExchange.Redis对象 /// </summary> private static ConnectionMultiplexer _redis; /// <summary> /// 代理类型 /// None = 0, /// Twemproxy = 1, /// </summary> private static int proxy = int.Parse(ConfigurationManager.AppSettings["Redis_Proxy"] ?? "0"); /// <summary> /// 是否为sentinel服务器 /// yes=1, /// no=0, /// </summary> private static int issentinel = int.Parse(ConfigurationManager.AppSettings["Redis_RedisIssentinel"] ?? "0"); /// <summary> /// sentinel模式下,redis主数据服务器的密码 /// </summary> private static string authPassword = ConfigurationManager.AppSettings["Redis_RedisIssentinel"]; /// <summary> /// serverName /// </summary> private static string serviceName = ConfigurationManager.AppSettings["Redis_ServiceName"]; /// <summary> /// 得到StackExchange.Redis单例对象 /// </summary> public static ConnectionMultiplexer Instance { get { if (_redis == null || !_redis.IsConnected) { lock (_locker) { if (_redis == null || !_redis.IsConnected) { _redis = GetManager(); return _redis; } } } return _redis; } } /// <summary> /// 构建链接 /// </summary> /// <param name="connectionString"></param> /// <returns></returns> private static ConnectionMultiplexer GetManager() { return GetCurrentRedis(); } /// <summary> /// 每个连接串用逗号分开,sentinel不支持密码 /// </summary> /// <returns></returns> static ConnectionMultiplexer GetCurrentRedis() { var connectionString = ConfigurationManager.AppSettings["Redis_Host"]; ConnectionMultiplexer conn; var option = new ConfigurationOptions(); option.Proxy = (Proxy)proxy;//代理模式,目前支持TW //sentinel模式下自动连接主redis if (issentinel == 1) { var configArr = connectionString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); configArr.ToList().ForEach(i => { option.EndPoints.Add(i); }); option.TieBreaker = "";//这行在sentinel模式必须加上 option.CommandMap = CommandMap.Sentinel; conn = ConnectionMultiplexer.Connect(option); for (int i = 0; i < option.EndPoints.Count; i++) { try { connectionString = conn.GetServer(option.EndPoints[i]).SentinelGetMasterAddressByName(serviceName).ToString(); Console.WriteLine("当前主master[{0}]:{1}", i, connectionString); break; } catch (RedisConnectionException ex)//超时 { continue; } catch (Exception ex) { continue; } } } return ConnectionMultiplexer.Connect(connectionString + ",password=" + authPassword); } }
消息队列:
入队
/// <summary> /// 消息队列-入队 /// </summary> static void ListLeftPush() { while (true) { string msg = $"{DateTime.Now:HH:mm}-{globaxId}-{Thread.CurrentThread.ManagedThreadId}-{StringExtend.GetRanString(8)}"; RedisManager.Instance.GetDatabase(RedisConfig.DemoDb).ListLeftPush(RedisConfig.DemoKey, msg); globaxId++; Console.WriteLine($"LeftPush:{msg}"); Task.Delay(500); Thread.Sleep(500); } }
出队:
/// <summary> /// 消息队列-出队 /// </summary> static void ListLeftPush() { while (true) { //ListLeftPush var msg = RedisManager.Instance.GetDatabase(RedisConfig.DemoDb).ListLeftPop(RedisConfig.DemoKey); if (!msg.IsNullOrEmpty) { Console.WriteLine($"出队:{msg}"); Task.Delay(200); } else { Thread.Sleep(1000); } } }
效果:
4.2发布订阅:
发布
/// <summary> /// 发布 /// </summary> static void Publish() { while (true) { lock (lockObj) { string msg = $"{DateTime.Now:HH:mm}-{globaxId}-{StringExtend.GetRanString(8)}"; var sub = RedisManager.Instance.GetSubscriber(); sub.Publish(RedisConfig.DemoChannel1, msg); Console.WriteLine($"Publish:{msg}"); globaxId++; } Task.Delay(200); Thread.Sleep(500); } }
订阅
/// <summary> /// 订阅 /// </summary> static void Subscribe() { while (true) { lock (lockObj) { // string msg = $"Publish:{DateTime.Now:HH:mm}-{globaxId}-{StringExtend.GetRanString(8)}"; var sub = RedisManager.Instance.GetSubscriber(); sub.Subscribe(RedisConfig.DemoChannel1, SubHandel); } Task.Delay(200); Thread.Sleep(500); } } static void SubHandel(RedisChannel cnl, RedisValue val) { if (!val.IsNullOrEmpty) { Console.WriteLine($"Subscribe{val},线程:{Thread.CurrentThread.ManagedThreadId},是否线程池:{Thread.CurrentThread.IsThreadPoolThread}"); } else { Thread.Sleep(1000); } }