Java中的锁(四)利用读写锁实现高性能网页缓存

news2024/9/21 22:42:24

文章目录

  • 背景
  • Ehcache2源码解析-如何实现缓存网页
  • 读写锁ReentrantReadWriteLock解析
    • 读写锁的特性
    • 读写锁是如何实现的?
  • 如何将Ehcach2-web的源码迁移到Ehcach3中?/ 如何自定义Filter实现高性能网页缓存?

背景

在我们的销售页面,有一个类似日历的控件,用户可以在该控件中查找当前月份中可以买票的活动。当多个用户访问该控件时,看到的内容是一样的,没必要每个用户发起的请求再去数据库查一遍。为了提高用户体验和避免大促期间该页面给服务器带来压力,我们决定对该控件的响应进行缓存。早期使用Ehcache2的SimplePageFragmentCachingFilter实现。

由于Ehcache2不再维护,我们决定将Ehcache2迁移到Ehcache3。在将Ehcache2迁移到Ehcache3的过程中,发现Ehcache2下的ehcache-web在Ehcache3中不再支持,现有项目中仍使用ehcache-web的SimplePageCachingFilter来缓存网页,于是决定copy SimplePageCachingFilter源码并使用 Ehcache3进行改写。在这个过程中发现了此SimplePageCachingFilter的实现利用里Java的读写锁。

Ehcache2源码解析-如何实现缓存网页

  1. 缓存网页的核心逻辑在于net.sf.ehcache.constructs.web.filter.CachingFilter#buildPageInfo在这里插入图片描述
  2. blockingCache的get方法如下所示在这里插入图片描述
  3. 先拿到一个锁,该锁是net.sf.ehcache.concurrent.ReadWriteLockSync的实例在这里插入图片描述
    该类的内部有一个Java的ReentrantReadWriteLock
  4. 多线程并发时,拿到锁之后先去获取读锁,拿到之后立刻释放掉。然后去拿写锁,如果第一次拿到写锁则返回的Element对象是null,此时写锁未释放,其他并发的线程拿不到写锁就等待一定时间,此时间可配置。在这里插入图片描述
  5. 拿到写锁之后则返回到第1步,调用buildPage,最后将该对象blockingCache.put进去,写锁在这里释放在这里插入图片描述
  6. 总结一下Ehcache2的实现网页缓存的逻辑,通过配置Filter的url-pattern,在浏览器端请求该url时会对response进行缓存。具体的缓存逻辑是由Java的读写锁ReentrantReadWriteLock完成的,使用ReentrantReadWriteLock确实能解决大量并发请求一个网页内容时的性能问题

读写锁ReentrantReadWriteLock解析

读写锁的特性

直接看注释

  1. 多线程并发时,如果都去获取读锁,则不互斥;如果此时有线程拿到了写锁,再去获取读锁,则需要等待写锁释放在这里插入图片描述
  2. 获取写锁时,如果此时没有其他线程拿到读锁或写锁,则直接获取;如果其他线程此时拿着读锁或写锁,则需等到锁的释放在这里插入图片描述

读写锁是如何实现的?

在Java中的锁(二)实现自定义锁中提到了,如果想要自定义锁,需要实现Lock接口+重写AQS的方法,并在实现的Lock接口中调用AQS的模板方法,这些方法最终会调用重写的AQS方法。

  1. 看一下它的主要结构,可以看到它的实现是按照上面我们所说的思路实现在这里插入图片描述

  2. 以读锁的lock方法为例,调用AQS的模板方法acquireShared,该方法会最终调用ReentrantReadWriteLock内部类Sync中的tryAcquireShared方法
    在这里插入图片描述

如何将Ehcach2-web的源码迁移到Ehcach3中?/ 如何自定义Filter实现高性能网页缓存?

看了上面的逻辑和读写锁的特性,实现起来就很简单了

  1. 自定义一个Filter,该Filter在缓存网页时使用Ehcache3。具体做法是将网页的Response放到Ehcache中
  2. 那怎么提高 高并发下对同一个网页的访问性能呢?使用读写锁
  3. 每个需要缓存的网页url中应该都有一个标识,此标识作为缓存的key
  4. 当多个并发请求都请求同一个网页时,拿到key去cache中找,找到则直接返回
  5. 找不到则开始获取读锁,拿到读锁什么都不做,直接释放;如果拿不到读锁,则等待
  6. 释放完读锁,立刻去竞争写锁,拿到写锁之后,先判断此时cache中有没有,因为当前线程可能不是第一个拿到写锁的线程,之前的写锁可能已经将内容写入cache中了,有则直接释放写锁;cache中没有则开始将网页的Response写入到cache中,然后释放写锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2094567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django+Vue酒店推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者&…

Linux文件操作(二)

Linux文件操作(二) 导语文件和目录维护chmodchownlink及其变体dir及其变体chdir和getcwd 扫描目录opendirreaddirtelldirseekdirclosedir示例程序 错误处理strerrorperror /procfcntlmmap相关mmapmsyncmunmap 总结参考文献 导语 文件操作的第二部分&…

juzige/Monitoring-System-基于Java语言的光伏监控系统

Photovoltaic-Monitoring-System-Based-on-Java-Language 基于Java语言的光伏监控系统光伏发电系统光伏软件系统光伏监控系统源码光伏发电系统源码-智电云 一、 介绍 光伏光伏发电预测逆变器监控逆变器数据采集光伏运维光伏电站光伏功率预测光伏监控系统光伏发电系统光伏软件…

【CSS in Depth 2 精译_022】3.6 一招搞定容器内元素间距的问题 + 3.7 本章小结

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结) 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位(已完结) 2.1 相对…

jQuery入门(六)jQuery实现瀑布流分页案例

一、瀑布流分页案例分析 1.1) 功能分析: 鼠标下拉,加载分页数据(10条) ,如下图: 案例分析: 1.2) 如何确定当前显示的数据已经浏览完毕? 公式:(滚动条距底部的距离 滚动条上下滚动的距离 当…

【Python篇】Python 类和对象:详细讲解(下篇)

文章目录 Python 类和对象:详细讲解(下篇)15. 接口和协议(Interfaces and Protocols)15.1 什么是接口?15.2 协议的基本概念例子:定义飞行协议详细解释输出示例 16. 装饰器模式(Decor…

A02、Java编程性能调优(02)

1、Stream如何提高遍历集合效率 1.1、什么是Stream 现在很多大数据量系统中都存在分表分库的情况。例如,电商系统中的订单表,常常使用用户 ID 的 Hash 值来实现分表分库,这样是为了减少单个表的数据量,优化用户查询订单的速度。 …

ZYNQ-Utlscale-RFSOC看门狗

ZYNQ-Utlscale-RFSOC看门狗复位 ZYNQ-Utlscale-RFSOC 看门狗的程序网上里程很少,开源资料也是几乎没有,最近需要用到这个功能,来来回回搞了一周才搞定。刚开始参考ZYNQ7000的资源,发现MPSOC不适用。很感谢下面的几篇文章&#xf…

探索TinyDB:轻量级数据库的优雅之旅

文章目录 探索TinyDB:轻量级数据库的优雅之旅背景:为何选择TinyDB?TinyDB是什么?如何安装TinyDB?简单库函数使用方法场景应用常见Bug及解决方案总结 探索TinyDB:轻量级数据库的优雅之旅 背景:为…

【电子通识】电子元器件可靠性基本概念

什么是电子元器件 电子元器件是电子产品的基本组成单元, 是电子元件和电子器件的总称。 通常电子元件指的是无源元件, 电子器件指的是有源器件。无源元件是对所供给的电能执行被动操作(如耗散、储蓄或释放等)的元件, 如…

《普通人学AI指南PDF》免费下载破10万。。。

你好,我是郭震 普通人如何开始AI,用好AI? 我在今年制作的《普通人学AI指南》PDF,从中或许能帮你找到答案: 1 PDF背景介绍 此PDF我是今年开始着手制作,到6月8日终版,中间历经反复多次修改&#x…

LabVIEW布尔值比较与信号状态上升沿下降沿检测

在 LabVIEW 编程中,布尔值的比较不仅是逻辑运算的重要组成部分,还广泛应用于信号的上升沿和下降沿检测。通过理解 True > False 这样的基本表达式,以及如何在程序中检测信号的状态变化,开发者可以有效地控制系统行为&#xff0…

内存管理篇-17解开页表的神秘面纱-上

--好像并没有解开。。 1.遗留的一些问题 (1)页表存储在内存的什么地方?页表服用的对象就是MMU,主要就为了MMU单元翻译的时候提供作用,因此能存放在MMU中的TLB缓存中,也可能存放在内存中。但是在内存中的什…

【MATLAB】matlab生成的图像如何导出(三种方法教会你)

我们经常使用matlab生成各类的图,如何将其导出,导出为何种类型。 方法一:选择 matlab 生成的图形界面 " Figure 1 " 的菜单栏 " 编辑 " — " 复制图窗 " , 就可以将图像拷贝到 Word 文档中 打开 Word 文档 ,…

远程调用以及注册中心Nacos

小编目前大一,刚开始着手学习微服务的相关知识,小编会把它们整理成知识点发布出来。我认为同为初学者,我把我对知识点的理解以这种代码加观点的方式分享出来不仅加深了我的理解,或许在某个时候对你也有所帮助,同时也欢…

YOLOv5课堂行为识别系统+GUI界面

课堂行为检测 gui/课堂行为识别系统/YOLOv5课堂行为识别/ yolov5/opencv/计算机视觉/python程序/深度学习/pytorch 数据集标注/配置好环境程序可直接运行/带UI界面/代码数据集/代码数据集 [功能]图片识别/视频识别/摄像头识别 损失/准确率等数据可在ten…

Golang 教程3——包

Golang 教程3——包 注意,该文档只适合有编程基础的同学,这里的go教程只给出有区别的知识点 文件结构 前置工作 在文件testproject01目录下执行 ‘go mod init gocode/testproject01’ (base) PS E:\Goproject\src\gocode\testproject01> go mo…

Linux学习——Ubuntu上QT添加资源

在我们平时的车载控制屏幕上一般不会只有文字和黑白的按钮,为了美观和容易操作,在设计的时候一般会添加图片或者是图标,来让界面的人机交互达到最好,那么我们今天就来学习一下如何在QT中添加资源图片! 1.传输照片&…

easy_fastapi Python 后端开发框架

GitHub easy_fastapi by one-ccs 遵循 MIT 开源协议 Easy FastAPI 基于 FastAPI 开发的后端框架,集成了 SQLAlchemy、Pydantic、Alembic、PyJWT、PyYAML、Redis 等插件,旨在提供一个高效、易用的后端开发环境。该框架通过清晰的目录结构和模块化设计&am…

GNU/Linux - Linux kernel memory access

User space memory access from the Linux kernel An introduction to Linux memory and user space APIs By M. Jones 10 August 2010 Archive date: 2023-08-31 虽然字节可能是 Linux 中内存的最低可寻址单位,但页面才是内存的可管理抽象。本文首先讨论 Linux …