Scut:Redis 资源管理器

核心文件是:RedisConnectionPool.cs

对象池类的通用泛型封装:ObjectPoolWithExpire<T>

1. 主要变量

        private static ICacheSerializer _serializer;     //redis 存储内容的序列化器
        private static RedisPoolSetting _setting;        //redus 他、应遵循的配置
        private static ConcurrentDictionary<string, ObjectPoolWithExpire<RedisClient>> _poolCache;   //字典结构:每个 key 对应一个 pool 的集合
        private static RedisInfo _currRedisInfo;

2. 初始化

        public static void Initialize(RedisPoolSetting setting, ICacheSerializer serializer)
        {
            _setting = setting;         //RedisPoolSetting 按默认配置加载的配置
            _serializer = serializer;   //采取的序列化器
            //init pool
            string key = GenratePoolKey(setting.Host, setting.DbIndex);     //127.0.0.1:6379#0 是首个管理 redisclient-pool 的 key
            var pool = GenrateObjectPool(setting);                          //建立对象池,主要是为泛型类注入 factory 方法,以及池深度、对象生命周期参数
        private static ObjectPoolWithExpire<RedisClient> GenrateObjectPool(RedisPoolSetting setting)
        {
            return new ObjectPoolWithExpire<RedisClient>(() => CreateRedisClient(setting), true, setting.PoolTimeOut, setting.MaxWritePoolSize / 10);
        }
            for (int i = 0; i < pool.MinPoolSize; i++)
            {
                pool.Put();
            }
            _poolCache[key] = pool;
            InitRedisInfo();  
        }

3. RedisClient 获取、读、写操作

句柄获取:

        public static RedisClient GetClient()
        {
             return GetOrAddPool(_setting);
        public static RedisClient GetOrAddPool(RedisPoolSetting setting)
        {
            var key = GenratePoolKey(setting.Host, setting.DbIndex);
            var lazy = new Lazy<ObjectPoolWithExpire<RedisClient>>(() => GenrateObjectPool(setting));  //根据配置找到pool的key,使用key检索到pool
            ObjectPoolWithExpire<RedisClient> pool = _poolCache.GetOrAdd(key, k => lazy.Value);          //在目标pool 获取一个 redisclient
            return pool.Get();
        }

        }

读取:

  先来看下应用层是如何加载数据的:

        public static object[] GetAllEntity(string personalId, params  Type[] entityTypes)
        {
            //todo: trace GetAllEntity
            var watch = RunTimeWatch.StartNew("Get redis data of persionalId:" + personalId);
            if (entityTypes.Length == 0) return null;

            byte[] keytBytes = ToByteKey(personalId);  //将私有ID转化成二进制流
            var redisKeys = new List<string>();
            foreach (var type in entityTypes)           //遍历所有要获取数据的类型
            {
                redisKeys.Add(GetRedisEntityKeyName(type));
            }
            try
            {
                byte[][] valueBytes = null;
                ProcessReadOnly(client =>
                {
                    var values = new List<byte[]>();
                    using (var p = client.CreatePipeline())
                    {
                        foreach (var key in redisKeys)  //使用redis管道,一次性执行多条读取命令
                        {
                            string k = key;
                            p.QueueCommand(cli => ((RedisNativeClient)cli).HGet(k, keytBytes), values.Add);  //将类型与私有ID组合成rediskey,将值获取到value中
                        }
                        p.Flush();
                    }
                    valueBytes = values.ToArray();  
                    //valueBytes = client.Eval(script, redisKeys.Count, redisKeys.ToArray());
                });
                watch.Check("redis get");
                if (valueBytes != null)
                {
                    var result = new object[entityTypes.Length];
                    for (int i = 0; i < entityTypes.Length; i++)  //遍历每个类型,将二进制流反序列化成对象
                    {
                        var type = entityTypes[i];
                        var val = i < valueBytes.Length ? valueBytes[i] : null;
                        result[i] = val == null || val.Length == 0
                            ? null
                            : _serializer.Deserialize(val, type);
                    }
                    return result;  //得到对象数组后返回,从应用层来看,该API可用于一次性获取一个personalkey的多种多类型数据
                }
            }
            catch (Exception ex)
            {
                TraceLog.WriteError("Get redis data of persionalId:{0} error:{1}", personalId, ex);
            }
            finally
            {
                watch.Flush(true, 200);
            }
            return null;
        }

写入:

  这里只看一个最常用的事务写入,对一个hashid下的多个key事务性地写入数据。

     //该API的命名是更新,更新则包含写入与删除两个操作     private static void TransUpdateEntity(IRedisTransaction trans, string hashId, byte[][] keys, byte[][] values, byte[][] removeKeys)
        {
            if (keys.Length > 0)
            {
                trans.QueueCommand(c =>
                {
                    var cli = (RedisClient)c;
                    cli.HMSet(hashId, keys, values);  
                });
            }
            if (removeKeys.Length > 0)
            {
                trans.QueueCommand(c =>
                {
                    var cli = (RedisClient)c;
                    cli.HDel(hashId, removeKeys);
                });
            }
        }

  在看 RedisConnectionPool.cs 的过程中,发现了大量 SchemaSet 与 Cache 的使用,下个阶段重点分析 Scut 的这两个部分。

时间: 2024-08-25 03:15:24

Scut:Redis 资源管理器的相关文章

Win10重命名文件夹导致资源管理器卡顿的解决办法

我本机使用的是 Win10 1607,不清楚是因为什么原因导致重命名文件夹时资源管理器会被卡死,找了很长时间终于找到了解决办法,现在我把步骤粘出来以便后续遇到相同问题的朋友能及时解决. 其实操作很简单,只需要简单的三步: 1. 打开任意文件夹 2. 点击左上角菜单栏中的"文件"按钮,选择"更改文件夹和搜索选项",如下图所示: 3. 在弹出的文件夹选项窗口中,依次点击"清除文件资源管理器历史记录"后的"清除"按钮和"还

unity 资源管理器设计

资源管理器,顾名思义,就是管理游戏中的所有资源,包括加载资源,回收资源,销毁资源等等.下面这个资源管理器主要提供了对assetbundle异步加载功能,Resources的加载没有放在里面. 一.使用方法 1.在进入游戏前调用Init(),加载一个资源的名称列表 2.调用AsynGetAsset(string name, Action<UnityEngine.Object> callback)方法(异步) 说明,这里的资源列表是从bundle_list列表中解析出来的,并且有一个manifes

文件服务器资源管理器

文件服务器资源管理器就三部分内容,分别是 配额,文件屏蔽管理,存储报告管理. 磁盘配合: 先说配额的应用方式,配额是先建立配额模板,在配额设置里面要应用配额的文件夹或者磁盘然后绑定上要用的配额模板即可,也可以 采取自定义的设置来做 这里要重点说一下 红框里面的问题,好多人容易在这个地方犯错误,1.在路径上创建配额是在这个文件夹一下的路径上(也可以理解为这个文件夹里面的文件总数不能超过配合) 2.在现有子文件夹贺新文件夹中自动创建配合是在这个文件夹一下的路径下所创建的文件夹大小都收这个配额的限制(

Jtree(节点的渲染+资源管理器)(2)

上一次我们建立一个比较简单的资源管理器,这次我们说一下上面的资源管理器的问题,并且得尽量的贴近windows的资源管理器. 这样一个简单的资源管理树就完成了,下面我们说说它的问题: ① 图片和外观和Windows有差距 这个我们可以通过设置L&F和通过前面写的Renderer那样设置新的图片解决,不是大问题. ② 文件夹里文件多时展开会很慢,会导致界面假死 这个我们可以自己写一个缓加载的TreeNode,让它继承于DefaultMutableTreeNode,在它里面定义加载标示,然后使用Swi

10gocm-&gt;session5-&gt;数据库管理实验-&gt;GC资源管理器资源消耗组演示

<GC资源管理器> 官方文档:administrator's Guide->24 Using the Database Resource Manager 使用率:在实际生产环境中使用的比较少 作用:限制数据库资源的使用,CPU  内存  undo表空间  IO  session 场合:当有多个应用使用一个数据库并且资源紧张时可用"资源管理器"调节 实现:可用GC完成也可用EM完成,还可以使用程序包完成 UI方式:简单,快捷,不容易出错 commend方式:设置复杂,命

win7频繁提示资源管理器已停止工作解决办法

今天上班打开电脑,总是弹出windows资源管理器已停止工作,点击下方的[重新启动],又恢复正常,但是不一会出现这个问题,如此反复,差不多一分钟左右出现一次,让人心烦意乱,没法工作! 一开始尝试了网上各种方法,诸如:修改注册表.进入安全模式杀毒.任务管理器 新建explorer.exe 进程.  甚至搞了一次 系统还原,折腾一上午,可是问题依旧,难道就为这重装一次系统???? 突然灵光一闪,想起查看 系统日志,果然找到一个错误日志, 错误应用程序名称: explorer.exe, 版本: 6.1

使用Windows Form 制作一个简易资源管理器

自制一个简易资源管理器----TreeView控件 第一步.新建project,进行基本设置:(Set as StartUp Project:View/Toolbox/TreeView) 第二步.开始添加节点 添加命名空间using System.IO; 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Dra

Windows 7 在资源管理器中显示软件快捷方式

该方法是利用资源管理器中储存网络位置的文件夹实现的, 不需要修改注册表. 效果如图: 操作方法: 在资源管理器中打开路径 "%appdata%\Microsoft\Windows\Network Shortcuts" 你可以往里面扔 快捷方式,可执行程序,甚至是文件夹.

自定义win8资源管理器左侧导航窗格的方法

Win8自定义资源管理器左侧导航窗格: 快捷键Win+R – 输入regedit: 删除“网络”项目 HKEY_CLASSES_ROOTCLSID{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}ShellFolder Attributes 键值 b0040064 修改 b0940064 删除“家庭组”项目 HKEY_CLASSES_ROOTCLSID{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}ShellFolder Attributes