做网站的例子建设网站的五个步骤

news/2025/9/22 15:25:45/文章来源:
做网站的例子,建设网站的五个步骤,网站运行环境配置,个人网站开发网#x1f468;‍#x1f393;作者简介#xff1a;一位大四、研0学生#xff0c;正在努力准备大四暑假的实习 #x1f30c;上期文章#xff1a;Redis#xff1a;原理速成项目实战——Redis实战4#xff08;解决Redis缓存穿透、雪崩、击穿#xff09; #x1f4da;订阅专… ‍作者简介一位大四、研0学生正在努力准备大四暑假的实习 上期文章Redis原理速成项目实战——Redis实战4解决Redis缓存穿透、雪崩、击穿 订阅专栏Redis原理速成项目实战 希望文章对你们有所帮助 上一篇文章讲解了缓存击穿问题以及解决缓存击穿问题的2种解决思路即互斥锁与逻辑过期这里将分别用这两种方式解决缓存击穿问题。 互斥锁、逻辑过期解决缓存击穿问题 互斥锁解决缓存击穿获取锁与释放锁方法封装业务逻辑修改测试 逻辑过期解决缓存击穿代码实现测试 互斥锁解决缓存击穿 根据上次讲解的互斥锁解决缓存击穿问题的方式我们可以将客户端查询数据的流程修改为如下 这里有比较关键的点这里的锁并不是我们平常用的锁平常的锁如果没有获取到的话就一直等待而这边我们需要自定义逻辑。 我们该如何自定义获取锁跟释放锁的逻辑我们可以利用Redis的一些数据结构的特性。 我们可以联想到之前学习Redis数据结构的时候用到的setnx当且仅当key不存在的时候setnx才会执行set操作 可以看到当我们的key已经是存在的情况下我们用setnx指令无法对其value进行修改。所以如果有无数线程进行setnx操作的时候只有第一个进行操作的线程可以写入value其他线程都会失败。 所以这就满足了我们所说的互斥锁的实现方式其实这也是分布式锁的一个基本原理当然真正的分布式锁还是比较复杂的。 而释放锁只需要执行del操作即可这样其他线程就可以获取到这个锁了 当然了最好别把锁永远加在那因为如果加了锁的线程他的工作没办法完成他就永远没办法释放锁因此我们在执行setnx操作的时候需要设置一下有效期。 获取锁与释放锁方法封装 进行业务逻辑编写之前我们可以先把获取锁与释放锁的方法给自定义一下 private boolean tryLock(String key){//尝试获取锁//opsForValue里面没有真正的setnx而是setIfAbsent表示如果不存在就执行set//值就随便设定一下重点是要获取到锁但是设定了TTL为10sBoolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, 10, TimeUnit.SECONDS);/*** 如果是直接返回flag可能会有拆箱操作造成空指针需要用BooleanUtil工具类* 因为Boolean不是基本类型的boolean是boolean的封装类*/return BooleanUtil.isTrue(flag); }private void unlock(String key){//释放锁stringRedisTemplate.delete(key); }业务逻辑修改 我们可以先把之前会出现缓存穿透的代码给封装起来封装成返回值为Shop类型的防止代码丢失之后章节的代码优化会解决缓存穿透问题 public Shop queryWithPassThrough(Long id){String key CACHE_SHOP_KEY id;//从Redis中查询商铺缓存存储对象可以用String或者Hash这里用StringString shopJson stringRedisTemplate.opsForValue().get(key);//判断是否存在if (StrUtil.isNotBlank(shopJson)) {//存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return shop;}//判断命中的是否是nullif (shopJson ! null){return null;}//不存在根据id查询数据库Shop shop getById(id);if (shop null){//存一个null到Redis中//这种没用的信息TTL没必要设置太长了这里我设置成了2minstringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//存在写入RedisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);//返回return shop; }同样的我们也可以把互斥锁解决缓存击穿的代码给单独封装起来注意我们不管获得互斥锁的线程有没有正常执行即便执行不成功也要在最后进行unlock因此我们要利用try…catch…finally public Shop queryWithMutex(Long id){String key CACHE_SHOP_KEY id;//从Redis中查询商铺缓存存储对象可以用String或者Hash这里用StringString shopJson stringRedisTemplate.opsForValue().get(key);//判断是否存在if (StrUtil.isNotBlank(shopJson)) {//存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return shop;}//判断命中的是否是nullif (shopJson ! null){//返回错误信息return null;}//未命中开始实现缓存重建//尝试获取互斥锁锁的key跟缓存的key不一样String lockKey lock:shop: id;Shop shop null;try {boolean isLock tryLock(lockKey);//判断是否获取成功if (!isLock){//失败则休眠并重试递归Thread.sleep(50);//单位ms//如果担心递归造成爆栈可以用循环一样的return queryWithMutex(id);}//成功就直接开始重建查询数据库并处理后保存到Redisshop getById(id);//由于在这里我们的数据库在本地重建很快所以添加休眠时间来模拟数据库重建过程的耗时长方便测试Thread.sleep(200);//不存在返回错误if (shop null){//存一个null到Redis中//这种没用的信息TTL没必要设置太长了这里我设置成了2minstringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//存在写入RedisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {//释放互斥锁unlock(lockKey);}//返回return shop; }queryById方法调用这个方法即可 Overridepublic Result queryById(Long id) {//缓存穿透的代码调用//Shop shop queryWithPassThrough(id);//互斥锁解决缓存击穿Shop shop queryWithMutex(id);if (shop null) {return Result.fail(店铺不存在);}//返回return Result.ok(shop);}测试 我们先把缓存清空然后运行代码再进行测试我们可以使用一个很好用的测试工具jmeter下载可以看下面这个博主的文章 jmeter下载教程 官网下载的实在是太慢了建议大家直接去这个博主的网盘里面下载。 我们可以这样设定我们设定我们的并发量为1000即有1000个线程同时访问 并配置好我们的http请求 运行完以后打开查看结果树 数据都查到了。 打开汇总报告可以看到我们的吞吐量接近200 如此大的数据量打下去但是我们的日志显示我们的数据库只执行了一次的查询语句 说明我们已经使用互斥锁成功避免了缓存击穿。 逻辑过期解决缓存击穿 代码实现 根据上次讲解的逻辑过期解决缓存击穿问题的方式我们可以将客户端查询数据的流程修改为如下 其实通常情况因为是热点key一般都是会出现在Redis里面的且因为我们没有设置TTL所以热点key是一定会一直存在的但为了严谨起见还是在判定缓存未命中的时候返回空。 我们主要解析一下主要的流程 1、我们判断一下缓存是否逻辑过期了如果没有过期我们直接返回信息到客户端即可 2、如果缓存逻辑过期了这个线程就尝试获取互斥锁如果获取成功说明它是第一个访问Redis的这个过期key的线程那么这个线程要做2件事 1返回这个旧数据给客户虽然数据是旧的但是这是一种暂时的牺牲 2开辟新的线程来进行缓存数据的重建重建完毕就释放这个互斥锁 3、除了第2种情况说的这个线程其他线程在知道自己访问的数据过期之后获取互斥锁都会失败那么这时候只需要直接返还数据给客户就好了可能是旧数据也可能是新数据第一个线程释放锁或者缓存数据重建成功了 首先我们要对Shop类增加逻辑过期时间这样一个字段一种方案是直接添加这种会违背开闭原则一种是可以新增加一个类并且类中包含了逻辑过期时间expireTime但是该怎么把这个属性添加到Shop里面呢可以让Shop继承这个类就可以获得这个类中的属性但同样会修改Shop这个类的源代码同样违背开闭原则所以最好的方法就是用关联来代替继承 如果不是很清楚的话可以先去学一下Java设计模式。 为了方便演示我们首先要进行一个数据预热我们需要有这个一个带着逻辑过期时间的店铺信息因此这里就先用单元测试的方式来让带着expireTime属性的数据存入Redis里面。 1、先编写一个类用于将带着逻辑过期时间的Shop存入Redis里面 public void saveShop2Redis(Long id, Long expireSeconds){//查询店铺数据Shop shop getById(id);//封装逻辑过期时间RedisData redisData new RedisData();//注入Shop对象redisData.setData(shop);//注入逻辑过期时间redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));//写入Redis不要设置TTLstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY id, JSONUtil.toJsonStr(redisData));}2、编写单元测试代码 SpringBootTest class HmDianPingApplicationTests {Resourceprivate ShopServiceImpl shopService;Testvoid testSaveShop(){shopService.saveShop2Redis(1L, 10L);}}我们运行这个单元测试后打开Redis客户端 证明已经存储成功。 现在正式开始用逻辑过期思想去解决缓存击穿的问题编写这个方法 private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10);public Shop queryWithLogicalExpire(Long id){String key CACHE_SHOP_KEY id;//从Redis中查询商铺缓存存储对象可以用String或者Hash这里用StringString shopJson stringRedisTemplate.opsForValue().get(key);//判断是否存在if (StrUtil.isBlank(shopJson)) {//未命中直接返回return null;}//命中先把json反序列化成对象RedisData redisData JSONUtil.toBean(shopJson, RedisData.class);JSONObject data (JSONObject) redisData.getData();//注意我们获取到了data信息以后返回的会是一个JSONObject的格式Shop shop JSONUtil.toBean(data, Shop.class);LocalDateTime expireTime redisData.getExpireTime();//判断是否过期if (expireTime.isAfter(LocalDateTime.now())){//未过期直接返回店铺信息return shop;}//已过期缓存重建//获取互斥锁String lockKey LOCK_SHOP_KEY id;//LOCK_SHOP_KEYlock:shop:boolean isLock tryLock(lockKey);//判断是否获取锁成功if (isLock){//成功获取锁开启独立线程来实现缓存重建用线程池来做CACHE_REBUILD_EXECUTOR.submit(() - {try {// 重建缓存this.saveShop2Redis(id, 20L);} catch (Exception e) {throw new RuntimeException(e);}finally {//释放锁unlock(lockKey);}});}//没有成功获取直接返回过期商铺信息return shop;}为了方便验证之前的缓存重建函数我们给他增加一个模拟重建时间200ms public void saveShop2Redis(Long id, Long expireSeconds) throws InterruptedException {//查询店铺数据Shop shop getById(id);Thread.sleep(200);//封装逻辑过期时间RedisData redisData new RedisData();//注入Shop对象redisData.setData(shop);//注入逻辑过期时间redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));//写入Redis不要设置TTLstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY id, JSONUtil.toJsonStr(redisData));}之前存储在Redis的数据其实早就已经逻辑过期了只是因为我们没有设置TTL它依旧存在于Redis里面只是可能已经过期了。 queryById直接改成调用该方法接着运行代码。 测试 1、我们直接将数据库中的餐厅名从101修改为102使得数据库数据与缓存不一致 2、打开jmeter进行测试这里把线程数改小一点不然不好观察 运行后观察结果树可以发现我们一开始查到的就是旧数据且这个过程会持续一段时间 到后面查询到的数据就是正常的数据了 查看idea后台可以发现我们只执行了一次重构说明只有一个线程操作了数据库其他数据库都被互斥锁拦住了 这也证明了逻辑过期方法会造成短暂的数据不一致的情况。 综上缓存击穿问题的两种解决思想其demo都已经调通。

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

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

相关文章

用ida插件快速审计函数调用

如果xref窗口会显示调用的伪代码,也许就不会有今天...前言 我又要在前言絮絮叨叨一下我是为什么要做这个小插件的了...就不看 在审查程序的漏洞的时候,我们可能会重点关注那么几个重点函数的调用:system肯定是重中之…

【ACM独立出版|往届已EI、Scopus检索|合作SSCI】第二届数字经济与计算机科学国际学术会议(DECS 2025)

第二届数字经济与计算机科学国际学术会议(DECS 2025)将于2025年10月17日至10月19日在中国武汉召开。本次会议旨在汇聚来自全球的学者、研究人员和业界专家,共同探讨数字经济与计算机科学领域的最新发展与应用。随着…

schematool -initSchema -dbType mysql

hive启动之前一定要用这条命令初始化

叶县红色家园网站建设公众号登陆

文章开始之前,建议安装一个显示网速的插件,不然你不知道到底有没有下载,也让生活有一点盼头 1.因为众所周知的原因(我dang的行为真的是让人失望),先更换一下ruby镜像源 $ gem sources --remove https://rub…

PostgreSQL 全表 count 优化实践:从 SeqScan 痛点分析到 heapam 改进与性能突破

本文整理自 IvorySQL 2025 生态大会暨 PostgreSQL 高峰论坛的演讲分享,演讲嘉宾:权宗亮。本文主要包括以下三部分:SeqScan 现状 heapam 改进 全表计数SeqScan 现状 我们使用了一个稍宽的 SeqScan 表,包含约 10-20 …

微信微网站建设平台wordpress改变友情链接顺序

文学迷 > 玄幻魔法 > 天命神相 > 第一千六百零七章 鸿蒙紫气,成圣之机 (上)第一千六百零七章 鸿蒙紫气,成圣之机功德金身只要达到了八十一重天,大圆满的境界,实力堪混元大罗级别的圣人,这听起来确实是一件吊炸…

逸阳网站建设的目标完整的网站优化放啊

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一. VRRP概述 VRRP---虚拟路由器冗余协议 VRRP(Virtual Router Redundancy Protocol)是一种用于在多个路由器之间创建虚拟路由器的协议。 VRRP使用了一系列协议来实现路…

学习做网站的孛校呼和浩特网站建设费用

更新:使用 滏阳河边捉蚯蚓 https://zhuanlan.zhihu.com/p/41297136上获取系统PDF文件和zotero.sqlite文件的代码,在此感谢!在zotero的library中删除参考文献条目后,有时PDF不会同步删除,尤甚是安装了zotfile插件后&…

登建设厅锁子的是哪个网站sharepoint 网站开发

这里 Allocation failed - JavaScript heap out of memory JavaScript堆内存不足,我们都知道 Node 是基于V8引擎,在一般的后端开发语言中,在基本的内存使用上没有什么限制,但是我去查阅了相关的资料才发现,在 Node 中通…

Lightroom Classic 2025:精细调控,呈现完美画质,专业级数字照片管理与后期处理全解析

Lightroom Classic 2024是一款由Adobe开发的数字照片后期处理软件,它为摄影师和摄影爱好者提供了一个全面、高效的后期处理平台。通过Lightroom Classic 2024,用户可以轻松地对数字照片进行各种调整和修饰,以实现最…

负载分析和排查五

负载分析和排查五明白 ✅ 我不会乱改行、不省略、不简化,而是在你提供的表格基础上补充更详细的内容:包括 问题原因分析 → 判断依据 → perf 排查命令 → 优化方向(C 语言/系统示例)。保证格式对齐,逐行完善。下…

管理网站建设源代码程序做网站用啥软件

题目描述 题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/ 思路 两个链表都是升序链表,新建一个链表,引入伪头节点作为辅助节点,将各节点添加到伪节点之后,再用一个cur节点指向新链表的…

langfuse从v2.70.1升级到V3.110(异机升级+数据迁移)

环境:Os:Centos 7langfuse:升级前版本:V2.70.1升级后版本:V3.110 说明:v3部署在新机器,我们需要将v2下的postgresql外挂的数据目录文件拷贝到v3下的外挂数据目录说明:yaml资源清单文件直接下载,尽量不要复制粘贴,避免…

宿州医疗网站建设设计一个学院网站

后面我们写代码时,写完可能会出现没有执行权限什么的,所以我们要知道文件都有哪些权限和类型。 首先 就像我们之前目录结构图里面有个/dev,它就是存放设备文件的,也就是说,哪怕是一个硬件设备,例如打印机啥的&#xf…

20250518_信安一把梭_医院抓取流量

流量分析, 应急响应, 数据统计, 信安一把梭Tags:流量分析, 应急响应, 数据统计, 信安一把梭 0x00. 题目 医院脱库应急处理(医院抓取流量.pcapng)首次发起端口扫描的IP审计流量和日志快速定位扫描次数最多的IP审计流量…

tsx 图论选讲

P6880 [JOI 2020 Final] 奥运公交 / Olympic Bus 题意 给定一个含有 \(N\) 个点,\(M\) 条边的有向图,每条边从 \(U_i\) 指向 \(V_i\),经过这条边的代价为 \(C_i\)。 在最开始时,我们可以翻转至多一条边,即让这条边…

一个网站如何做双语这么做简单的网站

文章目录 一、背景二、Stack 和 Heap2.1 Stack2.2 Heap2.3 性能区别2.4 所有权和堆栈 三、所有权原则3.1 变量作用域3.2 String 类型示例 四、变量绑定背后的数据交互4.1 所有权转移4.1.1 基本类型: 拷贝, 不转移所有权4.1.2 分配在 Heap 的类型: 转移所有权 4.2 Clone(深拷贝)…

福建自适应网站建设专业的网页制作服务好

在下面的文章中,我们将向您展示如何使用Elementor和MemberPress在WordPress中轻松构建会员网站。这篇文章将涵盖WordPress会员网站设置过程、会员资格和受保护内容创建、重要页面和登录表单设计、电子邮件通知管理、报告等。 目录 什么是WordPress会员网站&#x…

网站备案需要具备什么条件模板的网站都有哪些内容

这个项目可以让用户管理学生的信息,包括学生的姓名、年龄、成绩等,并提供添加、编辑、删除、查询等功能。这个项目涉及到数据库操作、用户界面设计、数据验证等方面的技术。 代码示例: import tkinter as tk # 导入 Tkinter 库 import sqli…

平面ui设计网站用vs做网站原型

基于AFM的物质表面微观结构及力学性质表征仿真实验 说明: 本次实验为本科生《基础物理实验》课程中的虚拟实验部分,在虚拟实验平台中进行。 一、实验目的: 1. 掌握AFM的基本成像原理及系统结构; 2. 掌握AFM的基本操作技巧及操…