缓存篇~第七回 Redis实现基于方法签名的数据集缓存(可控更新,分布式数据缓存)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介:

本篇文章可以说是第六回 Microsoft.Practices.EnterpriseLibrary.Caching实现基于方法签名的数据集缓存(可控更新,WEB端数据缓存)的续篇,事实上,有EnterpriseLibrary.Caching也只是实现缓存持久化的一种方式,而Redis做为成熟的分布式存储中间件来说,实现这个数据集缓存功能显得更加得心应手,也更加满足大型网站的设计规则。(在多web服务器时(web端实现负载均衡,反向代理),EnterpriseLibrary.Caching显得没什么作为,而这时,分布式缓存就可以一显身手了,它可以很轻松的将缓存服务器部署到第三方服务器上,解决了上面的问题)

一个标准,多种实现,面向对象的真谛:多态性,如果你问我接口有什么用,那么本篇文章可以告诉你答案:根据不同的场合,使用不同的持久化方式去存储数据。

下面是缓存标准接口ICacheProvider

 /// <summary>
    /// 表示实现该接口的类型是能够为应用程序提供缓存机制的类型。
    /// 这可以有多种实现机制
    /// </summary>
    public interface ICacheProvider
    {
        #region Methods
        /// <summary>
        /// 向缓存中添加一个对象。
        /// </summary>
        /// <param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        void Add(string key, string valKey, object value);
        /// <summary>
        /// 向缓存中更新一个对象。
        /// </summary>
        /// <param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        void Put(string key, string valKey, object value);
        /// <summary>
        /// 从缓存中读取对象。
        /// </summary>
        /// <param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <returns>被缓存的对象。</returns>
        object Get(string key, string valKey);
        /// <summary>
        /// 从缓存中移除对象。
        /// </summary>
        /// <param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>
        void Remove(string key);
        /// <summary>
        /// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值的缓存是否存在。
        /// </summary>
        /// <param name="key">指定的键值。</param>
        /// <returns>如果缓存存在,则返回true,否则返回false。</returns>
        bool Exists(string key);
        /// <summary>
        /// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值和缓存值键的缓存是否存在。
        /// </summary>
        /// <param name="key">指定的键值。</param>
        /// <param name="valKey">缓存值键。</param>
        /// <returns>如果缓存存在,则返回true,否则返回false。</returns>
        bool Exists(string key, string valKey);
        #endregion
    }

而这次我们使用Redis来作为实现持久化的方式,看一个RedisCacheProvider代码,它为了兼容性,将Dictionary<string, object>类型改为了Dictionary<string, byte[]>类型,这种设计避免了很多错误,因为我们知道,数据在发送时,它会被序列化,而兼容性,

安全性,性能等最佳的方式就是二进制的方式,所以,我们使用它来对数据进行存储。

    /// <summary>
    ///使用redis方式进行缓存持久化
    /// </summary>
    internal class RedisCacheProvider : ICacheProvider, IDisposable
    {
        private readonly IRedisClient _cacheManager = Redis.Client.RedisManager.GetClient();
        static byte[] Serialize(object data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream();
            formatter.Serialize(rems, data);
            return rems.GetBuffer();
        }
        static object Deserialize(byte[] data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream(data);
            data = null;
            return formatter.Deserialize(rems);
        }
        public void Add(string key, string valKey, object value)
        {
            byte[] byteValue = Serialize(value);
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                Dictionary<string, byte[]> dict = null;
                if (tbl.ContainsKey(key))
                {
                    dict = (Dictionary<string, byte[]>)tbl.Lists[key][0];
                    dict[valKey] = byteValue;

                }
                else
                {
                    dict = new Dictionary<string, byte[]>();
                    dict.Add(valKey, byteValue);
                }
                Remove(key);
                tbl.Lists[key].Add(dict);
            }

        }

        public void Put(string key, string valKey, object value)
        {
            Add(key, valKey, value);
        }

        public object Get(string key, string valKey)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                if (tbl.ContainsKey(key))
                {
                    Dictionary<string, byte[]> dict = (Dictionary<string, byte[]>)tbl.Lists[key][0];
                    if (dict != null && dict.ContainsKey(valKey))
                        return Deserialize(dict[valKey]);
                    else
                        return null;
                }
            }
            return null;

        }

        public void Remove(string key)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                tbl.Lists[key].RemoveAll();
            }
        }

        public bool Exists(string key)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                return tbl.ContainsKey(key);
            }
        }

        public bool Exists(string key, string valKey)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                return tbl.ContainsKey(key) &&
                 ((System.Collections.Generic.Dictionary<string, byte[]>)tbl.Lists[key][0]).ContainsKey(valKey);
            }
        }

        public void Dispose()
        {
            _cacheManager.Dispose();
        }
    }

事实上,写到这里,我们的redis方法签名存储就完成了,配合上一篇文章,你可以设计出自己的缓存系统了,在这里再多说一句,本缓存系统用到的设计模式类似于策略模式,它对于一个完善功能,可以多种实现的策略,而对外只公开一个标准的对象,其它具体

的,完整功能的实现都使用了internal作为修饰符,来对外界隐藏。

本文转自博客园张占岭(仓储大叔)的博客,原文链接:缓存篇~第七回 Redis实现基于方法签名的数据集缓存(可控更新,分布式数据缓存),如需转载请自行联系原博主。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
23天前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
23天前
|
缓存 NoSQL Java
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
缓存与分布式锁、Redisson分布式锁、缓存数据一致性【必须满足最终一致性】
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
|
24天前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
|
2天前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
11 2
|
7天前
|
存储 缓存 NoSQL
解决Redis缓存击穿问题的技术方法
解决Redis缓存击穿问题的技术方法
24 2
|
7天前
|
缓存 NoSQL Redis
解决 Redis 缓存穿透问题的有效方法
解决 Redis 缓存穿透问题的有效方法
19 2
|
16天前
|
NoSQL 安全 Java
解决Unknown redis exception及event executor terminated错误的方法
解决这类问题时,保持耐心和细致是关键。通常,通过系统地检查和排除潜在原因,大多数问题最终都能被解决。
65 1
|
1月前
|
缓存 NoSQL 关系型数据库
MySQL与Redis缓存一致性的实现与挑战
在现代软件开发中,MySQL作为关系型数据库管理系统,广泛应用于数据存储;而Redis则以其高性能的内存数据结构存储特性,常被用作缓存层来提升数据访问速度。然而,当MySQL与Redis结合使用时,确保两者之间的数据一致性成为了一个重要且复杂的挑战。本文将从技术角度分享MySQL与Redis缓存一致性的实现方法及其面临的挑战。
64 2
|
2月前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
2月前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
60 0
下一篇
无影云桌面