首页 > 技术文章 > 用户中心接口对外数据缓存化的实践参考

hnsongbiao 2016-01-16 01:11 原文

最近在看通用权限管理系统提供用户中心接口,发现有不少变化,现将我的理解分享给大家:

用户中心对外提供了基础信息、权限的接口,刚开始的部署方式采用了如下图的方式,由于客户端及应用服务器的网络环境,接口服务器配置了多个电信运营商的网络链接;

最初在用户量不大的时候,调用接口时是直接访问数据库获取数据向应用服务器输出,随着客户端访问量的增大,用户中心库的压力也逐渐增大,为了保证接口的稳定性,减轻数据库压力,进行了缓存化改造,主要使用了Redis,并进行了读写分离,改造后的示意图如下:

 

基础信息管理应用系统主要是维护基础信息、权限配置的,可以直观的看到,改造后,基础信息在更新后会将数据缓存到Redis服务器,通过Redis的主从配置,进行了读写分离,接口服务器里将原有的访问数据库获取的方法全部改造为从Redis中获取,极大的提高了效率。

底层中封装好了Redis获取数据的方法,项目截图如下:

提供部分参考代码如下,可以根据这个思路进行缓存优化,提高效率:

 

namespace DotNet.Business
{
    using DotNet.Utilities;

    /// <summary>
    /// 用户数据的缓存独立库。
    ///
    /// 修改纪录
    ///
    ///        2016-01-07 版本:1.1 JiRiGaLa 实现读写分离。
    ///        2015-04-11 版本:1.0 JiRiGaLa 创建主键。
    ///
    /// <author>
    ///        <name>JiRiGaLa</name>
    ///        <date>2016-01-07</date>
    /// </author>
    /// </summary>
    public sealed partial class PooledRedisHelper
    {
        // Redis数据库
        public static int InitialDbUser = 6;

        private static PooledRedisClientManager instanceUser = null;

        public static PooledRedisClientManager InstanceUser
        {
            get
            {
                if (instanceUser == null)
                {
                    instanceUser = new PooledRedisClientManager(InitialDbUser, new string[] { BaseSystemInfo.RedisHosts });
                }

                return instanceUser;
            }
        }

        public static IRedisClient GetUserClient()
        {
            return InstanceUser.GetClient();
        }

        private static PooledRedisClientManager instanceUserReadOnly = null;

        public static PooledRedisClientManager InstanceUserReadOnly
        {
            get
            {
                if (instanceUserReadOnly == null)
                {
                    instanceUserReadOnly = new PooledRedisClientManager(InitialDbUser, new string[] { BaseSystemInfo.RedisReadOnlyHosts });
                }

                return instanceUserReadOnly;
            }
        }

        public static IRedisClient GetUserReadOnlyClient()
        {
            return InstanceUserReadOnly.GetClient();
        }
    }
}

设置和获取缓存的方法

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key">缓存主键</param>
        /// <returns>用户信息</returns>
        public static BaseUserEntity GetCache(string key)
        {
            BaseUserEntity result = null;

            if (!string.IsNullOrWhiteSpace(key))
            {
                // 2016-01-08 吉日嘎拉 实现只读连接,读写分离
                using (var redisClient = PooledRedisHelper.GetUserReadOnlyClient())
                {
                    result = redisClient.Get<BaseUserEntity>(key);
                }
            }

            return result;
        }

        /// <summary>
        /// 获取缓存
        /// 20151007 吉日嘎拉,需要在一个连接上进行大量的操作
        /// </summary>
        /// <param name="key">缓存主键</param>
        /// <returns>用户信息</returns>
        private static BaseUserEntity GetCache(IRedisClient redisClient, string key)
        {
            BaseUserEntity result = null;

            if (!string.IsNullOrWhiteSpace(key))
            {
                result = redisClient.Get<BaseUserEntity>(key);
            }

            return result;
        }

对外提供接口参考:

        /// <summary>
        /// 用户是否在某个角色里
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="systemCode">系统编号</param>
        /// <param name="userId">用户主键</param>
        /// <param name="roleCode">角色编号</param>
        /// <returns>在角色里</returns>
        public static bool IsInRoleByCode(BaseUserInfo userInfo, string systemCode, string userId, string roleCode)
        {
            bool result = false;

            string url = BaseSystemInfo.UserCenterHost + "/UserCenter/UserService";
            WebClient webClient = new WebClient();
            NameValueCollection postValues = new NameValueCollection();
            postValues.Add("system", BaseSystemInfo.SoftFullName);
            postValues.Add("systemCode", systemCode);
            postValues.Add("securityKey", BaseSystemInfo.SecurityKey);
            postValues.Add("function", "IsInRoleByCode");
            postValues.Add("userInfo", userInfo.Serialize());
            postValues.Add("userId", userId);
            postValues.Add("roleCode", roleCode);
            // 向服务器发送POST数据
            byte[] responseArray = webClient.UploadValues(url, postValues);
            string response = Encoding.UTF8.GetString(responseArray);
            if (!string.IsNullOrEmpty(response))
            {
                result = JsonConvert.DeserializeObject<bool>(response);
            }

            return result;
        }

 通过这一番改造,各个应用系统要获取基础信息,可以直接调用底层的方法,或者通过接口获取,同时接口实现了如果缓存没有数据或数据已过期会去数据库获取,同时进行数据缓存。

 

推荐阅读