当前位置: 首页 > news >正文

手写MyBatis第78弹:装饰器模式在MyBatis二级缓存中的应用:从LRU到防击穿的全方案实现

  1. MyBatis二级缓存装饰器模式深度解析:从LRU到防击穿的全方案实现

  2. 手写MyBatis缓存装饰器:SynchronizedCache与BlockingCache实战

  3. 装饰器模式在MyBatis缓存中的应用:灵活组合的架构设计

  4. 二级缓存高级特性:序列化、LRU淘汰、日志统计完整实现

  5. MyBatis缓存装饰器链:如何设计可扩展的CacheBuilder

目录

正文

一、装饰器模式在缓存架构中的核心价值

装饰器模式 vs 继承的优劣对比

二、核心缓存装饰器实现详解

1. SynchronizedCache:线程安全的基础保障

2. LoggingCache:缓存命中率监控

3. SerializedCache:对象序列化与副本保护

4. LruCache:内存资源智能管理

5. BlockingCache:防止缓存击穿的保护盾

三、CacheBuilder:装饰器的灵活组合器

四、装饰器执行顺序的架构考量

正确的顺序设计

顺序设计原则

五、生产环境中的装饰器实践

1. 性能敏感场景的优化

2. 分布式缓存集成

3. 缓存预热策略

六、装饰器模式的架构思想延伸

七、总结


  🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。文末有免费源码

免费获取源码。

更多内容敬请期待。如有需要可以联系作者免费送

更多源码定制,项目修改,项目二开可以联系作者
点击可以进行搜索(每人免费送一套代码):千套源码目录(点我)

2025元旦源码免费送(点我)

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。


    正文

    一、装饰器模式在缓存架构中的核心价值

    装饰器模式(Decorator Pattern)是MyBatis二级缓存架构的精髓所在。它通过动态组合的方式,为缓存功能添加各种增强特性,而不需要修改原有的缓存实现。这种设计符合开闭原则,使得系统具有良好的扩展性和灵活性。

    装饰器模式 vs 继承的优劣对比
    • 继承的局限性:如果使用继承,要实现所有功能组合需要创建大量子类

    • 装饰器的优势:通过组合方式,可以动态地、透明地添加功能

    二、核心缓存装饰器实现详解

    1. SynchronizedCache:线程安全的基础保障
    public class SynchronizedCache implements Cache {private final Cache delegate;public SynchronizedCache(Cache delegate) {this.delegate = delegate;}@Overridepublic synchronized void putObject(Object key, Object value) {delegate.putObject(key, value);}@Overridepublic synchronized Object getObject(Object key) {return delegate.getObject(key);}@Overridepublic synchronized Object removeObject(Object key) {return delegate.removeObject(key);}@Overridepublic synchronized void clear() {delegate.clear();}// 其他方法委托给delegate}

    设计要点:所有修改操作都需要同步,但同步粒度较粗,适合并发量不高的场景。

    2. LoggingCache:缓存命中率监控
     public class LoggingCache implements Cache {private final Cache delegate;private int hits = 0;private int requests = 0;public LoggingCache(Cache delegate) {this.delegate = delegate;}@Overridepublic Object getObject(Object key) {requests++;Object value = delegate.getObject(key);if (value != null) {hits++;}if (requests % 100 == 0) { // 每100次请求输出日志logHitRatio();}return value;}private void logHitRatio() {double ratio = (double) hits / requests * 100;System.out.printf("缓存命中率: %.2f%% (命中: %d, 总请求: %d)%n", ratio, hits, requests);}}

    监控价值:通过命中率分析缓存效果,指导缓存策略优化。

    3. SerializedCache:对象序列化与副本保护

    这是二级缓存中最关键的装饰器,解决对象共享的核心问题:

    public class SerializedCache implements Cache {private final Cache delegate;public SerializedCache(Cache delegate) {this.delegate = delegate;}@Overridepublic void putObject(Object key, Object value) {if (value == null || value instanceof Serializable) {delegate.putObject(key, serialize((Serializable) value));} else {throw new CacheException("缓存对象必须实现Serializable接口");}}@Overridepublic Object getObject(Object key) {Object value = delegate.getObject(key);return value != null ? deserialize((byte[]) value) : null;}private byte[] serialize(Serializable value) {try (ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos)) {oos.writeObject(value);return bos.toByteArray();} catch (IOException e) {throw new CacheException("序列化失败", e);}}private Serializable deserialize(byte[] value) {try (ByteArrayInputStream bis = new ByteArrayInputStream(value);ObjectInputStream ois = new ObjectInputStream(bis)) {return (Serializable) ois.readObject();} catch (Exception e) {throw new CacheException("反序列化失败", e);}}}

    为什么必须使用SerializedCache?

    1. 对象隔离:不同SqlSession获取的是不同对象实例,避免并发修改冲突

    2. 深度复制:确保缓存对象的完整性,防止浅拷贝带来的数据不一致

    3. 跨JVM支持:为分布式缓存奠定基础

    4. LruCache:内存资源智能管理
     public class LruCache implements Cache {private final Cache delegate;private final LinkedHashMap<Object, Object> keyMap;private Object eldestKey;public LruCache(Cache delegate, final int size) {this.delegate = delegate;this.keyMap = new LinkedHashMap<Object, Object>(size, 0.75f, true) {@Overrideprotected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {boolean tooBig = size() > size;if (tooBig) {eldestKey = eldest.getKey();}return tooBig;}};}@Overridepublic void putObject(Object key, Object value) {delegate.putObject(key, value);cycleKeyList(key);}@Overridepublic Object getObject(Object key) {keyMap.get(key); // 触发访问顺序更新return delegate.getObject(key);}private void cycleKeyList(Object key) {keyMap.put(key, key);if (eldestKey != null) {delegate.removeObject(eldestKey);eldestKey = null;}}}

    LRU算法精髓:通过LinkedHashMap的访问顺序特性,自动维护最近使用顺序。

    5. BlockingCache:防止缓存击穿的保护盾
     public class BlockingCache implements Cache {private final Cache delegate;private final ConcurrentHashMap<Object, ReentrantLock> locks;public BlockingCache(Cache delegate) {this.delegate = delegate;this.locks = new ConcurrentHashMap<>();}@Overridepublic Object getObject(Object key) {acquireLock(key);try {return delegate.getObject(key);} finally {releaseLock(key);}}@Overridepublic void putObject(Object key, Object value) {try {delegate.putObject(key, value);} finally {releaseLock(key);}}private void acquireLock(Object key) {Lock lock = locks.computeIfAbsent(key, k -> new ReentrantLock());lock.lock();}private void releaseLock(Object key) {Lock lock = locks.get(key);if (lock != null) {lock.unlock();locks.remove(key); // 清理空闲锁}}}

    防击穿原理:当多个线程同时查询同一个不存在的数据时,只有一个线程会访问数据库,其他线程等待结果。

    三、CacheBuilder:装饰器的灵活组合器

     public class CacheBuilder {private Cache delegate;public CacheBuilder(Cache delegate) {this.delegate = new PerpetualCache("default");}public CacheBuilder size(int size) {this.delegate = new LruCache(delegate, size);return this;}public CacheBuilder blocking() {this.delegate = new BlockingCache(delegate);return this;}public CacheBuilder serialized() {this.delegate = new SerializedCache(delegate);return this;}public CacheBuilder logging() {this.delegate = new LoggingCache(delegate);return this;}public CacheBuilder synchronized() {this.delegate = new SynchronizedCache(delegate);return this;}public Cache build() {return delegate;}}​// 使用示例Cache cache = new CacheBuilder(new PerpetualCache("userCache")).size(1000).serialized().blocking().logging().build();

    建造者模式优势:通过链式调用,直观地组合各种缓存特性。

    四、装饰器执行顺序的架构考量

    装饰器的包装顺序直接影响缓存行为:

    正确的顺序设计
     // 推荐顺序:从内到外Cache cache = new LoggingCache(           // 最外层:监控统计new BlockingCache(       // 防击穿保护new SynchronizedCache(   // 线程安全new SerializedCache(     // 序列化new LruCache(            // 淘汰策略new PerpetualCache()     // 基础存储)))));
    顺序设计原则
    1. 基础功能在内层:PerpetualCache作为存储核心

    2. 数据转换靠近核心:SerializedCache应在内层确保数据格式统一

    3. 并发控制在中层:SynchronizedCache/BlockingCache控制并发访问

    4. 监控统计在外层:LoggingCache最后包装以统计完整链路

    五、生产环境中的装饰器实践

    1. 性能敏感场景的优化
     // 高并发读场景:使用读写锁替代同步锁public class ReadWriteCache implements Cache {private final Cache delegate;private final ReadWriteLock rwLock = new ReentrantReadWriteLock();@Overridepublic Object getObject(Object key) {rwLock.readLock().lock();try {return delegate.getObject(key);} finally {rwLock.readLock().unlock();}}}
    2. 分布式缓存集成
     // Redis缓存装饰器public class RedisCache implements Cache {private final JedisPool jedisPool;private final String namespace;@Overridepublic void putObject(Object key, Object value) {try (Jedis jedis = jedisPool.getResource()) {jedis.setex(buildRedisKey(key), expireTime, serialize(value));}}}
    3. 缓存预热策略
     public class WarmUpCache implements Cache {private final Cache delegate;private final ScheduledExecutorService scheduler;public void scheduleWarmUp() {scheduler.scheduleAtFixedRate(this::warmUp, 0, 30, TimeUnit.MINUTES);}}

    六、装饰器模式的架构思想延伸

    装饰器模式的价值不仅限于缓存实现,它体现了重要的软件设计原则:

    1. 单一职责原则:每个装饰器只关注一个特定功能

    2. 开闭原则:新增功能不需要修改现有代码

    3. 组合优于继承:通过组合实现功能的灵活扩展

    这种设计思想可以应用到:

    • 日志系统的Appender装饰

    • 网络连接的Filter链

    • 业务逻辑的Interceptor栈

    七、总结

    MyBatis二级缓存的装饰器体系展示了优秀架构设计的魅力。通过合理的装饰器组合,可以构建出功能强大、性能优越、可维护性高的缓存系统。

    关键收获

    • 装饰器模式实现了功能的正交组合

    • SerializedCache解决了对象共享的核心问题

    • BlockingCache有效防止缓存击穿

    • CacheBuilder提供了优雅的配置方式

    • 装饰器顺序影响系统行为和性能

    在实际项目中,应根据具体场景选择合适的装饰器组合,并通过监控数据持续优化缓存策略。


    🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

    💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

    🔥🔥🔥(源码 + 调试运行 + 问题答疑)

    🔥🔥🔥  有兴趣可以联系我。文末有免费源码

    💖学习知识需费心,
    📕整理归纳更费神。
    🎉源码免费人人喜,
    🔥码农福利等你领!

    💖常来我家多看看,
    📕网址:扣棣编程
    🎉感谢支持常陪伴,
    🔥点赞关注别忘记!

    💖山高路远坑又深,
    📕大军纵横任驰奔,
    🎉谁敢横刀立马行?
    🔥唯有点赞+关注成!

    往期文章推荐:

    基于Springboot + vue实现的学生宿舍信息管理系统
    免费获取宠物商城源码--SpringBoot+Vue宠物商城网站系统 
    【2025小年源码免费送】

    ⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇点击此处获取源码⬇⬇⬇⬇⬇⬇⬇⬇⬇

    http://www.dtcms.com/a/415633.html

    相关文章:

  1. 山西网站开发二次开发拍卖网站功能需求文档
  2. 中文简洁网站设计图wordpress 导航菜单设置
  3. JavaWeb-Ajax、监听器、过滤器及对应案例和jstl补充
  4. 如何自己免费建网站做最优秀的自己演讲视频网站
  5. 文件包含与下载漏洞
  6. centos7.9下安装freeswitch-1.10.5.-release详细教程(极其简单)
  7. 慢慢来做网站多少钱互联网保险经纪公司十大排名
  8. 【开题答辩全过程】以 Springboot大学英语四、六级学习系统开题为例,包含答辩的问题和答案
  9. php网站开发有什么软件男人女人做性关系网站
  10. 网站访客qq获取原理南昌网站开发机构
  11. 获取淘宝商品视频API接口解析:通过商品链接url获取商品视频item_video
  12. k8s node 节点加入 matser 错误 cannot construct envvars
  13. 做个自己的网站需要多少钱桂林网络平台开发公司
  14. 网站的建设背景临沂seo推广
  15. 网站建设合同免费下载做网页公司有哪些
  16. 【TS6】Cherry Studio项目介绍
  17. 自己创免费网站网站建设人员构成
  18. 永远网站建设推荐商城网站建设
  19. 【探寻C++之旅】第十五章:哈希表
  20. 线程的生命周期
  21. 网站建设男装定位微信公众平台注册官网入口
  22. 廊坊seo网站排名ui设计培训班有用吗
  23. 公司网站定位建议广州手工活外发加工网
  24. 高光谱成像在壁画研究分析以及保护的应用
  25. 从试水到普及,AI 通识课全面爆发
  26. TCP/IP 的韧性:尽力而为 可靠传输协议
  27. 与做网站的人怎么谈判网页设计与制作的原则
  28. 咸宁网站建设价格有没有专做于投融资的网站
  29. 门户网站建设和运行招标公告如何在第三方网站做推广
  30. 南宁网站建设找哪家wordpress 技术类主题