首页 > 代码库 > 号召大伙完善一个IM系统---------C#+JS (二)-------服务端封装Redis

号召大伙完善一个IM系统---------C#+JS (二)-------服务端封装Redis

这个IM的服务端,使用的是Redis作为数据库

我一开始使用的redis的SDK是ServiceStack.Redis,但是据说它是收费的,测试版的一个小时内只能发送1000个请求??

后来,我改成使用StackExchange.Redis作为Sdk,并根据它的特点进行了一些封装。下面,介绍一下 为什么这样封装以及封装的内容。

我们先看一下封装后,是如何调用的(最终的目的就是要这样)

技术分享

 

使用关系型数据库(mysql,sqlserver..)时,我们都是有一个DAL层的,dal层的每个类,对应的是一张表,类里的方法,则是这张表的增删该查。

redis这个非关系型数据库,它不存在表这个概念,它只有一个库的概念。我刚接触redis,我喜欢把这个库当作是sqlserver中的一张表来理解。

但是redis存储数据使用的是key,value结构,所以我没办法按照以前的分层方式,建一个dal层,对每个库的操作进行封装。虽然可以这么做,但这样是不值得的。

 

操作redis类的封装,应该按照操作类型来(增,删,改,查),所以应该封装这几个类(Add,Delete,Update,Get),这里我们把update去掉。这里不需要update。redis会对相同的key进行赋值时,覆盖它的value,没有update一小个部分的做法。

我封装出来的是这样的(OpretionBase这个类,是他们的父类,父类记录的是通用的上下文

 技术分享      技术分享

 

OpretionBase中的上下文,全都是StackExchange.Redis中的定义。 IServer用于库的概况查询,ITransaction用于事务性操作,IDatabase用于一般性操作。

 

下面介绍一下最后一个类:OpretionPublic类(只有它向外部提供调用,这边我没办法对应上某个设计模式,只能贴个图,你们自己理解。但是外部调用很简单)

 public class OpretionPublic : IDisposable
    {
        //不要多次实例化这个类,不然会有bug的
        private static readonly ConnectionMultiplexer _client = ConnectionMultiplexer.Connect(Config.Config.redisHost);
      
        private static IServer _server = _client.GetServer(Config.Config.redisIP, Config.Config.redisPort);
        private static List<OpretionPublic> _options = new List<OpretionPublic>();

        private static object obj = new object();
        //redis的数据库的没有名称,只能通过一个数字去描述它
        public static OpretionPublic getOperation(int db)
        {
            Monitor.Enter(OpretionPublic.obj);
            var op = _options.FirstOrDefault(o => o._db == db);
            if (op != null)
            {
                Monitor.Exit(OpretionPublic.obj);
                return op;
            }
            else
            {
                var newop = new OpretionPublic(db);
                _options.Add(newop);
                Monitor.Exit(OpretionPublic.obj);
                return newop;
            }
        }

        public Add Add { get; set; }
        public Delete Delete { get; set; }
        public Get Get { get; set; }

        private ITransaction _tran;
        private int _db { get; set; }
        internal OpretionPublic(int db)
        {
            _db = db;
            var database = _client.GetDatabase(db);
            _tran = database.CreateTransaction();
            Add = new Add(database, _tran, _server);
            Delete = new Delete(database, _tran, _server);
            Get = new Get(database, _tran, _server);
        }

        void IDisposable.Dispose()
        {
            //Add.Dispose();
            //Delete.Dispose();
            //Get.Dispose();
        }

        public void commitTran()
        {
            _tran.Execute();
        }

    }

 

现在展示一下外部如何去调用(这样的调用方式是不是有ef的味道? 但是这里的跨库事务是不支持的,因为上下文是按库来进行创建的,每一个库都有它自己对应的上下文)

技术分享

 

号召大伙完善一个IM系统---------C#+JS (二)-------服务端封装Redis