Lind.DDD.RedisClient~对StackExchange.Redis调用者的封装及多路复用技术
两雄争霸
使用StackExchange.Redis的原因是因为它开源,免费,而对于商业化的ServiceStack.Redis
,它将一步步被前者取代,开源将是一种趋势,商业化也值得被我们尊重,毕竟人家研究代码也不容易,做商品也很正常,当然这不是我们今天的重点,今天主要说一下对StackExchange.Redis的封装,它与ServicesStack.redis最大的不同就是,它没有线程池的概念,这对于初学者绝对是个坑,大家使用时一定要注册,StackExchange.redis的对象一定要做成静态化的,或者单例的,不然,你的服务器的CPU将在不久的将来出现瓶颈,可以设想一下,网络socket只建立连接,而不被释放,是个什么味道!(平凡建立连接,用完释放,也是一种资料的浪费)
一家独占-多路复用
数据通信系统或计算机网络系统中,传输媒体的带宽或容量往往会大于传输单一信号的需求,为了有效地利用通信线路,希望一个信道同时传输多路信号,这就是所谓的多路复用技术(Multiplexing)。采用多路复用技术能把多个信号组合起来在一条物理信道上进行传输,在远距离传输时可大大节省电缆的安装和维护费用。
大叔定义:简单的说,就是一个连接,一个链路,供多个线程使用,发数据包,收数据包等!
Lind.DDD.RedisClient就简单了
/// <summary> /// StackExchange.Redis管理者 /// 注意:这个客户端没有连接池的概念,而是有了多路复用技术 /// </summary> public class RedisManager { /// <summary> /// 锁对象 /// </summary> private static object _locker = new object(); /// <summary> /// StackExchange.Redis对象 /// </summary> private static ConnectionMultiplexer instance; /// <summary> /// 得到StackExchange.Redis单例对象 /// </summary> public static ConnectionMultiplexer Instance { get { if (instance == null) { lock (_locker) { if (instance != null) return instance; instance = GetManager(); return instance; } } return instance; } } /// <summary> /// 构建链接,返回对象 /// </summary> /// <param name="connectionString"></param> /// <returns></returns> private static ConnectionMultiplexer GetManager() { string connectionString = ConfigConstants.ConfigManager.Config.Redis.Host; if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentNullException("请配置Redis连接串!"); } return ConnectionMultiplexer.Connect(connectionString); } }
对于多路利用的并发测试
[TestMethod] public void Redis_Async() { List<Action> actionList = new List<Action>(); actionList.Add(() => { for (int i = 0; i < 100; i++) { RedisClient.RedisManager.Instance.GetDatabase().SetAdd("test01", i.ToString()); Thread.Sleep(100); Console.WriteLine("test011" + i); } }); actionList.Add(() => { for (int i = 0; i < 100; i++) { RedisClient.RedisManager.Instance.GetDatabase().SetAdd("test02", i.ToString()); Thread.Sleep(10); Console.WriteLine("test012" + i); } }); Parallel.Invoke(actionList.ToArray()); }
通过测试和观察,我们可以看到,这个并发的线程同时使用一个RedisManager的实例,并没有出现阻塞的情况,即同一个链路,处理了多个任务!