java脚手架系列10-统一缓存、分布式锁

之所以想写这一系列,是因为之前工作过程中有几次项目是从零开始搭建的,而且项目涉及的内容还不少。在这过程中,遇到了很多棘手的非业务问题,在不断实践过程中慢慢积累出一些基本的实践经验,认为这些与业务无关的基本的实践经验其实可以复刻到其它项目上,在行业内可能称为脚手架,因此决定将此java基础脚手架的搭建总结下来,分享给大家使用。

注意由于框架不同版本改造会有些使用的不同,因此本次系列中主要使用基本框架是 spring-boo-2.3.12.RELEASE和spring-cloud.-Hoxton.SR12,所有代码都在commonFramework项目上:https://github.com/forever1986/commonFramework/tree/master

目录

  • 1 缓存
  • 2 分布式锁
    • 2.1 分布式锁的作用
    • 2.2 分布式锁的实现方式
    • 2.3 代码实践

1 缓存

我们知道,无论是数据库或者是文件系统,大部分都存在于磁盘之上,而磁盘往往是整个访问链路中速度最慢之一,因此如何快速避开磁盘访问,往往是业务需要解决性能问题之一,因此缓存就是为了这里而生。在数据库或者对象存储中,其实它们本身就是说过了缓存,而这里要将的缓存是基于业务层面的。在业务中,某些热点数据由于其访问量巨大,因此可以放入缓存中实现。下面就以redis为例,做一个redis集成到项目的脚手架:

参考common-redis子模块和manage-biz子模块

1)在common子模块下面新建common-redis子模块,该子模块的作用就是配置redis基本配置,以spring.factories方式发布
2)创建RedisConfig配置类,里面默认配置redisTemplate和stringRedisTemplate(同时使用@ConditionalOnMissingBean({RedisTemplate.class})注解,使得引用该子模块也可以自定义自己的Template)

注意:redis有2种不同的template(2种的key不能共享)
1.StringRedisTemplate:以String作为存储方式:默认使用StringRedisTemplate,其value都是以String方式存储
2.RedisTemplate:
1)使用默认RedisTemplate时,其value都是根据jdk序列化的方式存储
2)自定义Jackson2JsonRedisSerializer序列化,以json格式存储,其key与StringRedisTemplate共享,返回值是LinkedHashMap(本案例中使用该种方式)
3)自定义GenericJackson2JsonRedisSerializer序列化,以json格式存储,其key与StringRedisTemplate共享,返回值是原先对象(因为保存了classname)

package com.demo.redis;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {/*** 主要做redis配置。redis有2种不同的template(2种的key不能共享)* 1.StringRedisTemplate:以String作为存储方式:默认使用StringRedisTemplate,其value都是以String方式存储* 2.RedisTemplate:*    1)使用默认RedisTemplate时,其value都是根据jdk序列化的方式存储*    2)自定义Jackson2JsonRedisSerializer序列化,以json格式存储,其key与StringRedisTemplate共享,返回值是LinkedHashMap*    3)自定义GenericJackson2JsonRedisSerializer序列化,以json格式存储,其key与StringRedisTemplate共享,返回值是原先对象(因为保存了classname)*/@Bean@ConditionalOnMissingBean({RedisTemplate.class})public RedisTemplate redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate();template.setConnectionFactory(factory);//本实例采用Jackson2JsonRedisSerializerJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();template.setKeySerializer(stringRedisSerializer);template.setHashKeySerializer(stringRedisSerializer);template.setValueSerializer(jackson2JsonRedisSerializer);template.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}@Bean@ConditionalOnMissingBean({StringRedisTemplate.class})public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(factory);return template;}
}

3)在spring.factories配置RedisConfig类
4)在manage-biz子模块中引入common-redis

<dependency><groupId>org.example</groupId><artifactId>common-redis</artifactId><version>${project.version}</version>
</dependency>

5)在yaml配置文件中redis访问(由于manage-biz的yaml配置在nacos上面,因此需要nacos修改cloud-manage-biz-service文件配置)

spring:# redis配置redis:database: 1host: 127.0.0.1port: 6379password:timeout: 30000client-type: jedisjedis:pool:max-active: 1000max-idle: 100min-idle: 0maxWait: 1000

6)编写TestRedisController和TestRedisService演示redis存储对象和byte字节示例

2 分布式锁

2.1 分布式锁的作用

在数据库,我们对一个资源进行操作,比如更新一行数据,那么数据库根据你设置的事务级别,一般都会对其加锁,加锁的原因其实就是怕并发操作时,避免脏数据。
而在不同服务之间,其锁的概念也是有的。比如我们为了避免前端重复点击,一般会给前端返回一个key,然后前端提交数据时,将key返回给后端,后端验证是否同时有同一个key多个请求,如果存在则返回重复操作。

2.2 分布式锁的实现方式

常见的分布式锁实现有以下几种方式:
1)基于数据库实现分布式锁
2)基于zookeeper实现分布式锁
3)基于redis实现分布式锁

从理解的难易程度角度(从低到高) :数据库 > 缓存 > Zookeeper
从实现的复杂性角度(从低到高):Zookeeper >= 缓存 > 数据库
从性能角度(从高到低):缓存 > Zookeeper >= 数据库
从可靠性角度(从高到低):Zookeeper > 缓存 > 数据库

2.3 代码实践

参考子模块:common-redis和distributed-lock-service

本案例中使用redis来实现分布式锁,同时引入redisson框架(该框架封装了基于redis的分布式锁,让我们非常方便使用。另外如zookeeper也有Curator框架)
1)新建distributed-lock-service子模块,引入以下依赖:

<dependency><groupId>org.example</groupId><artifactId>common-redis</artifactId><version>${project.version}</version>
</dependency>
<!--redisson中已经引入spring-starter-web,因此无需在引入 -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.12.5</version>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

2)编写RedissonConfig,配置RedissonClient

package com.demo.redis.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissonConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String redisPassword;@Beanpublic RedissonClient getRedisson(){Config config = new Config();//单机模式  依次设置redis地址和密码config.useSingleServer().setAddress("redis://" + host + ":" + port);
//                setPassword(redisPassword);return Redisson.create(config);}
}

3)编写RedisLockController,实现一个扣取库存的分布式锁模拟场景
4)通过启动2台服务器(记得修改接口),然后分别访问2台服务器的/redisLock/exportInventory接口,查看扣取库存日志是否正确

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

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

相关文章

LeetCode 每日一题 最小差值 II

最小差值 II 给你一个整数数组 nums&#xff0c;和一个整数 k 。 对于每个下标 i&#xff08;0 < i < nums.length&#xff09;&#xff0c;将 nums[i] 变成 nums[i] k 或 nums[i] - k 。 nums 的 分数 是 nums 中最大元素和最小元素的差值。 在更改每个下标对应的值之后…

HotSpot VM

HotSpot VM 是 Sun JDK 和 OpenJDK 中所带的虚拟机&#xff0c;也是目前使用范围最广的 Java 虚拟机。它在 Java 技术中起着至关重要的作用&#xff0c;其历史可追溯至 1997 年 Sun 公司收购设计它的 “Longview Technologies” 小公司。HotSpot VM 最初并非为 Java 语言开发&a…

算法笔记day06

目录 1.添加逗号 2.跳台阶 3.扑克牌顺子 1.添加逗号 添加逗号_牛客题霸_牛客网 算法思路&#xff1a; 按照提议模拟即可&#xff0c;从后向前遍历字符串&#xff0c;遍历三个字符之后&#xff0c;将其插入将这三个字符插入到新的字符串中再加上逗号。 #include <iostrea…

Thymeleaf模板引擎教程(详细总结)

Thymeleaf 是一个服务器端 Java 模板引擎&#xff0c;能够处理 HTML 、 XML 、 CSS 、 JAVASCRIPT 等模板文件。 Thymeleaf 模板可以直接当作静态原型来使用&#xff0c;它主要目标是为开发者的开发工作流程带来优雅的自然 模板&#xff0c;也是 Java 服务器端 HTML5 开…

Docker设置日志滚动

问题描述 Docker 容器中的进程会将打印到控制台(console)的日志保存到容器的目录下&#xff0c;默认的 Docker 配置不带有日志的回滚。会在自己的容器目录下往同一个日志文件中不停写入&#xff0c;最后会导致磁盘空间占满的问题。 解决方案 方案一&#xff1a;全局范围内修…

一文掌握Cephadm部署Ceph存储集群

&#x1f4da; 博客主页&#xff1a; StevenZeng学堂 &#x1f389; 本文专栏: 一文读懂Kubernetes一文读懂Harbor云原生安全实战指南云原生存储实践指南 ❤️ 摘要&#xff1a;随着企业数据量的增长和存储需求的复杂化&#xff0c;Ceph因其高可扩展性和灵活性&#xff0c;能…

网络安全的五大误区,你中招了吗?

在数字化时代&#xff0c;网络安全问题日益突出&#xff0c;许多人在使用网络过程中存在一些误区&#xff0c;导致个人信息泄露、财产损失等问题。本文将为您揭示网络安全的五大误区&#xff0c;帮助您提高安全防范意识。 误区一&#xff1a;使用复杂密码就一定安全 许多人认为…

考研读研生存指南,注意事项

本视频课程&#xff0c;涉及考研读研的方方面面&#xff0c;从考研初试→复试面试→研究生生活→导师相处→论文专利写作混毕业&#xff0c;应有尽有。有了他&#xff0c;你的研究生生涯稳了。 读研考研注意事项&#xff0c;研究生生存指南。_哔哩哔哩_bilibili 一、考研初试注…

临阵磨枪!这份软考中级集成案例分析答题万金油赶紧收藏

在系统集成项目管理工程师案例分析科目的考试中&#xff0c;主要分为“计算题”和“分析题”两大类。 计算题主要围绕着进度管理和成本管理进行出题&#xff0c;比如挣值计算、网络图、关键路径等等&#xff0c;一般占据一道大题。 而分析题呢主要占三道大题&#xff0c;主要…

前端开发 环境变量 process.env.NODE_ENV 是什么

背景&#xff1a; 前端开发过程中&#xff0c;解决Access跨域问题&#xff0c;使用跨域代理&#xff0c;注意这里是指前端的跨域代理&#xff0c;所以这里配置的只适用于开发环境。至于生产环境一般由后端配置跨域代理&#xff0c;一般使用ngnix解决生产环境的跨域代理。 一、…

新款任天堂switch游戏机方案,支持4K60HZ投屏方案,显示器,手柄方案

据传任天堂将推出新的一代的switch掌机&#xff0c;而新款掌机将支持4K60HZ投屏 都2402年了再做1080P确实有点不太象话了 4K60HZ相较于1080P能够提升很多游戏体验&#xff0c;这时不管是HDMI显示器或者是VR眼睛清晰度都会让人舒服很多。 不过新一代的任天堂似乎也在PD协议上…

家政小程序搭建,数字化市场发展下的意义

家政服务行业作为当下社会生活中不可或缺的行业&#xff0c;需求量在逐渐增加&#xff0c;行业发展也趋向多样化。 随着数字化的浪潮&#xff0c;家政行业逐渐向数字化、智能化升级发展&#xff0c;推动行业高质量发展&#xff0c;迎合现代化发展趋势&#xff0c;这一转型为行…

【趣学C语言和数据结构100例】

【趣学C语言和数据结构100例】 问题描述 利用递归函数调用方式&#xff0c;将所输入的 5 个字符&#xff0c;以相反顺序打印出来 给定一个不多于 5 位的正整数&#xff0c;要求: 1. 求它是几位数&#xff0c;2. 逆序打印出各位数字 一个 5 位数&#xff0c;判断它是不是回文…

GPU泡沫破灭前夜

GPU泡沫破灭前夜 GPU(图形处理器)是近年来快速发展的领域&#xff0c;因为GPU能够加速计算机图形的处理速度&#xff0c;使得计算机游戏和视频渲染变得更加高效和流畅。然而&#xff0c;GPU泡沫破灭前夜&#xff0c;这种繁荣景象已经变得不太真实。 GPU市场的繁荣始于2010年&…

网站分享丨UU在线工具

在日常的工作、学习和生活中&#xff0c;我们常常会遇到各种各样需要借助工具来解决的问题。今天就给大家介绍一个功能强大、涵盖众多实用工具的在线平台 ——UU 在线工具。 一、丰富多样的工具分类 1.文档处理类&#xff1a; PDF 工具&#xff1a;提供了 PDF 转 Word、PDF 合…

IDEA中文乱码�

这篇文章网上到处都是&#xff0c;但我写作的初衷是为了更好地审视自己的作品&#xff0c;并通过不断的总结与反思来提升自我。 文章目录 前言原因分析解决方案一、设置字体为支持中文的字体二、设置字符编码为 UTF-8三、修改 IDEA 配置文件&#xff0c;让其支持中文编码第一种…

资讯 | 财富通科技政务协同办公管理软件通过麒麟软件适配认证

2024年9月25日&#xff0c;财富通科技研发的政务协同办公管理软件成功通过中国国产操作系统麒麟软件的适配认证。本次认证是继公司区块链产品“基于区块链的企业及人员资质数字证书服务平台”认证以后得第二次认证。这一成就标志着财富通科技在推动国产软件生态建设方面迈出了坚…

Java项目-基于springboot框架的广场舞团系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

【无标题】如何使用yolo-v8 实现自定义目标检测

如何使用yolo-v8 实现自定义目标检测 训练数据集准备搭建环境安装anaconda配置python虚拟环境安装yolo-v8以及labelimg图片标注工具 编写配置文件和训练脚本文件编写yaml配置文件(文件名为dataset.yaml)编写模型训练代码&#xff08;文件名称为yolotrain.py&#xff09;运行训练…

Debug-029-el-table实现自动滚动分批请求数据

前情提要 最近做了一个小优化&#xff0c;还是关于展示大屏方面的。大屏中使用el-table展示列表数据&#xff0c;最初的方案是将数据全部返回&#xff0c;确实随着数据变多有性能问题&#xff0c;有时请求时间比较长。这里做的优化就是实现列表的滚动到距离底部一定高度时再次请…