幂等的几种解决方案以及实践
目录
什么是幂等?
解决幂等的常见解决方案:
唯一标识符案例
数据库唯一约束 案例
乐观锁案例
分布式锁(Distributed Locking)
实践精选方案
首先 为什么不直接使用分布式锁呢?
自定义实现幂等组件!
RepeatExecuteLimitAutoConfiguration
repeatExecuteLimitAspect防重复幂等 切面
本地锁
localLockCache是本地锁缓存,可根据锁名和锁类型(公平锁/非公平锁)来获得ReentrantLock的实例
本地锁的作用:
分布式锁
设置幂等标识的作用
注意
什么是幂等?
在web项目中,幂等性同样是一个重要的概念。这主要是因为在网络和分布式系统中,由于网络的不稳定性和其他潜在问题,可能会导致请求被重复发送。如果一个操作不是幂等的,那么重复执行该操作可能会产生不一致的结果或副作用。例如,一个非幂等的操作可能会导致数据被重复添加、更新或删除,从而破坏数据的一致性。
因此,JavaWeb项目需要保证幂等性,主要是为了确保无论请求被发送一次还是多次,系统都能产生相同的结果。这有助于避免由于重复请求导致的数据不一致或其他潜在问题。实现幂等性的方法有很多种,包括但不限于使用数据库唯一索引、乐观锁、分布式锁、令牌等技术。
总的来说,幂等性是JavaWeb项目中一个非常重要的概念,它有助于确保系统的稳定性和数据的一致性。通过实现幂等性,我们可以有效地处理重复请求,并减少由于网络不稳定或其他原因导致的潜在问题。
解决幂等的常见解决方案:
-
唯一标识符(Unique Identifiers): 为每个请求生成一个唯一的标识符(如UUID),并将其作为请求的一部分发送。当接收到请求时,服务器可以检查该标识符是否已处理过。如果已处理,则拒绝或忽略该请求;如果未处理,则处理该请求并记录标识符。
-
数据库唯一约束: 使用数据库的唯一约束(如主键或唯一索引)来确保即使多次尝试插入相同的数据,也只有一条记录会被保存。如果尝试插入重复的数据,数据库会抛出异常,服务器可以捕获这个异常并返回幂等性的响应。
-
乐观锁(Optimistic Locking): 使用版本号或时间戳来检查数据是否已被其他操作修改过。在更新数据时,如果版本号或时间戳与预期的不符,则拒绝更新并返回冲突信息。这样,即使多次尝试更新相同的数据,也只有一次会成功。
-
分布式锁(Distributed Locking): 在分布式系统中,可以使用分布式锁来确保同一时间只有一个节点能够执行某个操作。这可以防止多个节点同时处理相同的请求,从而实现幂等性。
唯一标识符案例
-
使用 setex 命令存储ID并设置过期时间,避免内存泄漏。
-
适用于高并发场景,如支付、订单创建等。
// 生成唯一ID(客户端)
String requestId = UUID.randomUUID().toString();// 服务端校验(基于Redis)
public class IdempotencyService {private Jedis jedis; // Redis客户端public boolean checkRequest(String requestId) {if (jedis.exists(requestId)) {return false; // 已处理,拒绝重复请求}jedis.setex(requestId, 3600, "processed"); // 存储ID并设置过期时间return true;}
}
数据库唯一约束 案例
-
场景:用户注册防重复。
实现思路:数据库表中为关键字段(如用户名、邮箱)添加唯一索引,插入重复数据时抛出异常。
-
数据库自动拒绝重复数据,无需额外代码判断
-
适用于新增操作(如注册、订单号生成)
// JPA实体类定义
@Entity
@Table(name = "users", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String email; // 唯一字段
}// 插入逻辑
try {userRepository.save(user); // 尝试插入
} catch (DataIntegrityViolationException e) {throw new DuplicateKeyException("邮箱已存在"); // 捕获唯一约束异常
}
乐观锁案例
场景:库存扣减防超卖。
实现思路:通过版本号字段控制并发更新,仅当版本匹配时才允许操作。
-
JPA的
@Version
注解自动管理版本号 -
更新失败时抛出
OptimisticLockingFailureException
,需重试或提示用户。
// 实体类添加版本号字段
@Entity
public class Product {@Idprivate Long id;private int stock;@Versionprivate int version; // 乐观锁版本号
}// 更新逻辑(JPA)
@Transactional
public void deductStock(Long productId, int quantity) {Product product = productRepository.findById(productId).orElseThrow();if (product.getStock() >= quantity) {product.setStock(product.getStock() - quantity);productRepository.save(product); // 自动检查版本号} else {throw new InsufficientStockException();}
}
分布式锁(Distributed Locking)
场景:分布式系统中全局资源操作(如优惠券发放)。
实现思路:使用Redisson实现分布式锁,确保同一时刻仅一个节点执行关键逻辑。
-
tryLock
设置超时时间防止死锁 -
适用于跨服务或集群环境下的资源竞争场景
// 基于Redisson的分布式锁
public class CouponService {private RedissonClient redissonClient;public void grantCoupon(String userId) {RLock lock = redissonClient.getLock("COUPON_GRANT_" + userId);try {if (lock.tryLock(0, 10, TimeUnit.SECONDS)) { // 尝试获取锁// 执行业务逻辑(如发放优惠券)grantCouponToUser(userId);}} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}}
}
方案 | 适用场景 | 优点 | 缺点 |
唯一标识符 | 高并发请求(如支付) | 实现简单,适合分布式环境 | 需维护ID存储(如Redis) |
数据库唯一约束 | 数据唯一性要求(如注册) | 依赖数据库特性,无需额外逻辑 | 不适用于更新操作 |
乐观锁 | 低冲突更新(如库存扣减) | 无锁竞争,性能较高 | 需处理版本冲突和重试逻辑 |
分布式锁 | 跨服务资源竞争(如秒杀) | 强一致性保证 | 实现复杂,可能影响性能 |
实践精选方案
除了单纯实现幂等,而是要在保证实现幂等的前提下,还要考虑高并发下的高效率执行,不能影响程序的性能和吞吐量
基于上述这些要求,最终选择利用redis来实现,而在对使用redis上,Redisson又是非常优秀的开源中间件,其中的分布式锁是非常的经典,项目中也对分布式锁做了封装,使用起来灵活而方便,而这次幂等组件也是对Redisson基础上进行封装,保证了性能,支持MQ中间件和用户请求的幂等。
首先 为什么不直接使用分布式锁呢?
为什么还要额外设计出幂等组件?首先直接使用分布式锁是可以实现幂等的,当然业务逻辑验证也要做验证,但其实分布式锁会浪费一些性能。
分布式锁的特点是多个请求并发执行,这些请求是来自不同的用户,也就是这些请求虽然要依次等待锁执行,但最终还是要把这些请求都执行完的(执行时间太长超时的异常情况排除),总结起来就是都要获得锁,没有获得锁的请求,也要争取获得锁接着执行。
幂等的特点也是多个请求并发执行,但这些请求是来自同一个用户,也就是说这些请求只要保证第一个请求能执行,其余的请求要直接拒绝掉,总结起来就是只有第一个请求获得锁执行就可以,其余的请求看到已经上了锁,那么就要直接结束掉。
自定义实现幂等组件!
通过定义注解实现哦!
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface RepeatExecuteLimit {/*** 业务名称** @return name*/String name() default "";/*** key设置** @return key*/String[] keys();/*** 在多长时间内一直保持幂等,如果不配置则以执行方法为准*/long durationTime() default 0L;/*** 当消息执行已经出发防重复执行的限制时,提示信息*/String message() default "提交频繁,请稍后重试";}
RepeatExecuteLimitAutoConfiguration
public class RepeatExecuteLimitAutoConfiguration {@Bean(LockInfoType.REPEAT_EXECUTE_LIMIT)public LockInfoHandle repeatExecuteLimitHandle(){return new RepeatExecuteLimitLockInfoHandle();}@Beanpublic RepeatExecuteLimitAspect repeatExecuteLimitAspect(LocalLockCache localLockCache,LockInfoHandleFactory lockInfoHandleFactory,ServiceLockFactory serviceLockFactory,RedissonDataHandle redissonDataHandle){return new RepeatExecuteLimitAspect(localLockCache, lockInfoHandleFactory,serviceLockFactory,redissonDataHandle);}
}
RepeatExecuteLimitAutoConfiguration是自动装配类,用于加载需要的对象,repeatExecuteLimitHandle是锁键名处理器、repeatExecuteLimitAspect是幂等切面。
repeatExecuteLimitAspect防重复幂等 切面
@Slf4j
@Aspect
@Order(-11)
@AllArgsConstructor
public class RepeatExecuteLimitAspect {private final LocalLockCache localLockCache;private final LockInfoHandleFactory lockInfoHandleFactory;private final ServiceLockFactory serviceLockFactory;private final RedissonDataHandle redissonDataHandle;@Around("@annotation(repeatLimit)")public Object around(ProceedingJoinPoint joinPoint, RepeatExecuteLimit repeatLimit) throws Throwable {// 指定保持幂等的时间long durationTime = repeatLimit.durationTime();// 提示信息String message = repeatLimit.message();Object obj;// 获取锁信息LockInfoHandle lockInfoHandle = lockInfoHandleFactory.getLockInfoHandle(LockInfoType.REPEAT_EXECUTE_LIMIT);// 获取锁名String lockName = lockInfoHandle.getLockName(joinPoint,repeatLimit.name(), repeatLimit.keys());// 幂等标识String repeatFlagName = PREFIX_NAME + lockName;// 获得幂等标识String flagObject = redissonDataHandle.get(repeatFlagName);//如果幂等标识的值为success,说明已经有请求在执行了,这次请求直接结束if (SUCCESS_FLAG.equals(flagObject)) {throw new DaMaiFrameException(message);}// 获得本地锁ReentrantLock localLock = localLockCache.getLock(lockName,true);// 本地锁尝试获取boolean localLockResult = localLock.tryLock();// 如果本地锁获取失败,说明有其他请求在执行,这次请求直接结束if (!localLockResult) {throw new DaMaiFrameException(message);}try {// 获得分布式锁ServiceLocker lock = serviceLockFactory.getLock(LockType.Fair);// 尝试获取分布式锁boolean result = lock.tryLock(lockName, TimeUnit.SECONDS, 0);// 加锁成功执行if (result) {try{// 再次获取幂等标识flagObject = redissonDataHandle.get(repeatFlagName);// 如果幂等标识的值为success,说明已经有请求在执行了,这次请求直接结束if (SUCCESS_FLAG.equals(flagObject)) {throw new DaMaiFrameException(message);}obj = joinPoint.proceed();if (durationTime > 0) {try {// 业务逻辑执行成功后,设置 指定幂等保持时间 设置请求标识redissonDataHandle.set(repeatFlagName,SUCCESS_FLAG,durationTime,TimeUnit.SECONDS);}catch (Exception e) {log.error("getBucket error",e);}}return obj;} finally {lock.unlock(lockName);}}else{// 获得锁失败,说明有其他请求在执行,这次请求直接结束throw new DaMaiFrameException(message);}}finally {localLock.unlock();}}
}
RepeatExecuteLimitAspect是负责幂等执行的切面也是核心流程。
负责幂等的切面顺序要优先于分布式锁前,所以这里是-11。
这个实践中给我最大的震撼是本地锁、分布式锁、还有本地缓存的使用!
本地锁
ReentrantLock localLock = localLockCache.getLock(lockName,true);
boolean localLockResult = localLock.tryLock();
if (!localLockResult) {throw new DaMaiFrameException(message);
}
localLockCache是本地锁缓存,可根据锁名和锁类型(公平锁/非公平锁)来获得ReentrantLock的实例
public class LocalLockCache {/*** 本地锁缓存* */private Cache<String, ReentrantLock> localLockCache;/*** 本地锁的过期时间(小时单位)* */@Value("${durationTime:2}")private Integer durationTime;@PostConstructpublic void localLockCacheInit(){localLockCache = Caffeine.newBuilder().expireAfterWrite(durationTime, TimeUnit.HOURS).build();}/*** 获得锁,Caffeine的get是线程安全的* */public ReentrantLock getLock(String lockKey,boolean fair){return localLockCache.get(lockKey, key -> new ReentrantLock(fair));}
}
LocalLockCache其实是用Caffeine缓存来保存的锁信息,并可以设置锁实例的保存时间,默认是2小时,这个时间可以根据durationTime
来进行配置,如果时间过大,那么锁的实例就会过多,对项目的内存就会有压力。如果时间过小,那么构建锁的频率就会增加,性能就会受到影响,使用时,可根据业务特点进行灵活配置
Caffeine是基于Java 1.8的高性能本地缓存库,由Guava改进而来,而且在Spring5开始的默认缓存实现就将Caffeine代替原来的Google Guava,官方说明指出,其缓存命中率已经接近最优值。实际上Caffeine这样的本地缓存和ConcurrentMap很像,即支持并发,并且支持O(1)时间复杂度的数据存取。二者的主要区别在于:
-
ConcurrentMap将存储所有存入的数据,直到你显式将其移除;
-
Caffeine将通过给定的配置,自动移除“不常用”的数据,以保持内存的合理占用。
因此,一种更好的理解方式是:Cache是一种带有存储和移除策略的Map。
本地锁的作用:
之所以先使用本地锁去加锁的原因是,可以很大程度上节省分布式锁的资源,虽然分布式锁是利用reids实现的,redis的性能又非常的高,但是它再高,依旧存在网络损耗,而本地锁的操作都是基于内存中,一个是内存中操作,一个是网络操作,前者的效率可是后者的几十倍差距。
如果一秒内有100个请求,服务的实例有5个,那么每个实例就有20个请求,这20个请求就可以靠本地锁来拦截掉,那么到分布式锁那里,就有5个请求来获得锁了,其余的95个请求都可以被提前结束掉。
这是一个经典的思想,优先考虑本地内存操作,经过本地内存操作后,再去操作第三方中间件。
分布式锁
当本地锁获得了锁之后,还要用分布式锁去尝试获得锁,因为本地锁只能保证当前自己的实例范围内能锁住请求,微服务多个实例部署的话,就需要分布式锁了
//加锁成功执行
if (result) {try{//再次获取幂等标识flagObject = redissonDataHandle.get(repeatFlagName);//如果幂等标识的值为success,说明已经有请求在执行了,这次请求直接结束if (SUCCESS_FLAG.equals(flagObject)) {throw new DaMaiFrameException(message);}//执行业务逻辑obj = joinPoint.proceed();if (durationTime > 0) {try {//业务逻辑执行成功 并且 指定了设置幂等保持时间 设置请求标识redissonDataHandle.set(repeatFlagName,SUCCESS_FLAG,durationTime,TimeUnit.SECONDS);}catch (Exception e) {log.error("getBucket error",e);}}return obj;} finally {lock.unlock(lockName);}
}else{//获取锁失败,说明已经有请求在执行了,这次请求直接结束throw new DaMaiFrameException(message);
}
当通过分布式锁工厂获取到客户端实例后,就会尝试去获取分布式锁了,如果加锁失败,说明之前已经有请求获得了锁在执行中没有释放掉,那么这次请求直接结束
如果加锁成功则执行业务逻辑joinPoint.proceed()
-
如果执行业务逻辑成功,如果设置了幂等保持时间,那么设置幂等标识
-
如果执行业务逻辑失败,那么直接释放锁
设置幂等标识的作用
有的小伙伴可能会好奇,为什么要设置幂等标识?直接使用本地锁+分布式锁不就可以实现幂等了吗?为什么多此一举?只使用本地锁+分布式锁的方法确实能实现幂等,但此项目是为了高并发的,考虑的细节要全面。
幂等包括用户请求幂等和MQ消息幂等
要介绍这两种的特点
-
用户请求的幂等特点是用户在短时间内多次的点击,比如说一秒内发出了10次请求,那么就第1次请求正常执行,而剩余9次请求要全部被拦截将请求直接结束掉,特点是短时间内的多次请求
-
MQ消息幂等特点是MQ为了保证消息的可靠性。在有些异常情况确实会重复投递的,比如说 某个服务监听到了消息,接着执行业务逻辑,但在执行过程中,这个服务宕机了,没有给MQ发送消息提交机制,MQ就会认为消息没有消费成功,就会再次投递。但其实这个逻辑都执行成功了,就差给MQ提交确认了。
这就需要保证幂等。而MQ的重试就没有用户多次重复请求那么频繁,可能会1分钟 5分钟 10分钟,这种情况就需要幂等标识,当有了标识后逻辑直接结束。
注意
有的小伙伴刚接触开发,对并发产生的细节问题不太清楚,比如幂等和分布式锁,直接使用就觉得没有问题了,但其实并不是这样,我们来举一个例子,比如说添加用户的操作
-
请求获得锁得到执行
-
开启事务
-
向数据库中添加用户
-
提交事务
这个流程其实是有问题的,比如说第一个请求添加了用户后释放了锁,第二个请求是重复提交的,也添加了用户,这两个用户就是重复的。所以要在第2步后,要有验证用户是否存在的步骤,这个属于业务验证,需要业务来实现,组件只能防止并发重复,并不能防止业务重复。正确的流程:
-
请求获得锁得到执行
-
开启事务
-
查询用户是否已存在
-
向数据库中添加用户
-
提交事务
相关文章:
幂等的几种解决方案以及实践
目录 什么是幂等? 解决幂等的常见解决方案: 唯一标识符案例 数据库唯一约束 案例 乐观锁案例 分布式锁(Distributed Locking) 实践精选方案 首先 为什么不直接使用分布式锁呢? 自定义实现幂等组件!…...
拥塞控制 流量控制 区别
对比项拥塞控制流量控制关注对象整个网络 是否过载接收方主机 是否处理不过来控制目标避免网络路由器、链路拥塞避免发送方发太快,接收方来不及处理发生原因网络中有太多数据包,引起排队、丢包接收方缓存能力有限实现方式基于网络状态动态调整发送速率基…...
AWS VPC架构师指南:从零设计企业级云网络隔离方案
一、VPC核心概念解析 1.1 核心组件 VPC:逻辑隔离的虚拟网络,可自定义IPv4/IPv6地址范围(CIDR块) 子网(Subnet): 公有子网:绑定Internet Gateway(IGW)&#…...
[逆向工程]什么是DLL注入(二十二)
[逆向工程]什么是DLL注入(二十二) 引言 DLL注入(DLL Injection) 是Windows系统下一种重要的进程控制技术,广泛应用于软件调试、功能扩展、安全检测等领域。然而,它也是一把“双刃剑”——恶意软件常借此实…...
极简远程革命:节点小宝 — 无公网IP的极速内网穿透远程解决方案
极简远程革命:节点小宝,让家庭与职场无缝互联 ——打破公网桎梏,重塑数字生活新体验 关键词:节点小宝|内网穿透|P2P直连|家庭网络|企业协作|智能组网节点小宝࿵…...
Vue生命周期脚手架工程Element-UI
一 Vue2.x生命周期 每个vue实例再被创建时都要经过一系列的初始化过程: 创建实例 装载模板 渲染模板等等 vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每个vue实例处于不同的生命周期时,对应的函数就会触发调用 https:…...
LeetCode[226] 翻转二叉树
思路: 使用递归,归根结底还是左右节点互相倒,那么肯定需要一个temp节点在中间传递,最后就是递归,没什么说的 代码: /*** Definition for a binary tree node.* public class TreeNode {* int …...
ConcurrentHashMap解析
ConcurrentHashMap解析 以下是对 Java 8 及以后版本 ConcurrentHashMap 源码的深入解析,涵盖其底层数据结构、并发控制机制、核心操作流程、扩容与迁移、树化/退化策略,以及性能特性。总体来说,ConcurrentHashMap 在 JDK 8 中摒弃了原有的 S…...
windows10 系统显示mov文件格式缩略图
最近做视频剪辑,有些mov格式文件,但是尝试用各种播放器默认播放,都没有缩略图可看, 很影响查看。 遂选择了个插件,来在windows10系统显示mov文件的缩略图。 1.下载安装 K-Lite Codec Pack (安装时一路Ne…...
力扣智慧思想小题,目录力扣.跳跃游戏(思想很重要)力扣.跳跃游戏II(还是思想)力扣.分发糖果力扣151.反转字符串中的单词力扣.轮转数组
目录 力扣.跳跃游戏(思想很重要) 力扣.跳跃游戏II(还是思想) 力扣.分发糖果 力扣151.反转字符串中的单词 力扣.轮转数组 字符 a97 A65; JRE:Java运行时候的环境 JDK: JAVA开发套件(工具包) java原本是.java文件,编译成.class字节码文件 八种基本数据…...
【LangChain基础系列】深入全面掌握文本分类
文本分类是自然语言处理领域中的一个重要任务,旨在将文本数据自动归类到预定义的类别中。它是实现信息检索、智能推荐、情感分析等应用的基础技术之一。 应用场景 1. 垃圾邮件过滤 :自动识别并过滤垃圾邮件。 2. 情感分析 :分析用户评论或社交媒体内容…...
AI赋能高频PCB信号完整性优化
在5G通信、自动驾驶、卫星导航等高频技术快速迭代的今天,**信号完整性(SI)**已成为高频PCB设计的核心挑战。如何在高密度布线、复杂电磁环境中实现信号的精准传输?猎板PCB通过**AI驱动设计优化**、**材料与工艺创新**以及**智能化…...
如何从播放器构造角度研究 Media3 源码
Jetpack Media3 是 Android 提供的现代化媒体播放库。 Media3 的核心组件包括: ExoPlayer:播放器核心,负责协调媒体播放。MediaSource:定义媒体来源(如 DASH、HLS、Progressive)。TrackSelectorÿ…...
大模型深度思考与ReAct思维方式对比
大模型的「深度思考」与「ReAct思维方式」虽然都涉及复杂推理过程,但并非完全等同的概念。它们在目标、机制和应用场景上存在显著差异,以下是具体分析: 一、概念本质差异 深度思考(Deep Reasoning) 定义:泛…...
视频编解码学习六之视频采集和存储
视频采集的核心原理是用光学元件(如摄像头)将光信号转换为电信号进行传输和存储。 摄像头的主要功能是将光学图像转换为电信号(模拟或数字),核心流程如下: 1. 光学成像 镜头组:聚焦光线到感光…...
Linux开发工具【中】
目录 一、vim 1.1 插入模式 1.2 底行模式 1)set nu 2)set nonu 3) /XXX n 4)!command 5)vs other 1.3 补充 1) 批量化操作 2)批量化替换 : 3)快速定位&am…...
Django之账号登录及权限管理
账号登录及权限管理 目录 1.登录功能 2.退出登录 3.权限管理 4.代码展示合集 这篇文章, 会讲到如何实现账号登录。账号就是我们上一篇文章写的账号管理功能, 就使用那里面已经创建好的账号。这一次登录, 我们分为三种角色, 分别是员工, 领导, 管理员。不同的角色, 登录进去…...
深度学习Y7周:YOLOv8训练自己数据集
🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 一、配置环境 1.官网下载源码 2.安装需要环境 二、准备好自己的数据 目录结构: 主目录 data images(存放图片) annotati…...
2025年渗透测试面试题总结-某服面试经验分享(附回答)(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 1. 协议类型 2. OSI七层模型 3. 网络层协议 4. HTTP请求头 5. 常见端口 6. 中间件解析漏洞 7. CS…...
手写Promise的静态方法
最近对promise原理的理解,手写下其中的静态方法。 手写Promise的静态方法 1. Promise.resolve2. Promise.reject3. Promise.all4. Promise.any5. Promise.race6. Promise.allSettled 1. Promise.resolve 首先就是resolve方法,它会接收一个值࿰…...
Python Cookbook-7.8 使用 Berkeley DB 数据库
任务 你想将一些数据做持久化处理,而且也想体验一下BerkeleyDB数据库的简洁和高效。 解决方案 如果以前在你的计算机中安装过 BerkeleyDB,Python标准库附带的bsddb包(以及可选的 bsddb3,用于访间Berkeley DBrelease 3.2数据库)可以被用来作…...
云手机虚拟地址技术的运营场景
云手机虚拟地址技术通过模拟地理位置(GPS/IP地址)与设备指纹,结合云端虚拟化能力,在多个商业场景中实现突破性应用。以下是其核心运营场景及技术实现路径的深度解析: 一、跨境电商与区域化运营 本地化合规与流量突破 目…...
操作符详解(2)
目录 9 结构成员访问操作符 9.1.2 结构体变量的定义和初始化 9.2 结构体成员的直接访问 10 操作符的属性:优先级、结合性 10.1 优先级 11 表达式求值 11.1 整型提升 11.2 算术转换 11.3 问题表达式解析 11.3.1 表达式1 11.3.2 表达式2 11.3.3 表达式3 1…...
责任链设计模式
一、核心接口定义 MyAbstractChainHandler<T> 接口继承自 Ordered 接口,用于实现链式处理逻辑。 import org.springframework.core.Ordered;public interface MyAbstractChainHandler<T> extends Ordered {void handle(T requestParam);String getCha…...
【银河麒麟高级服务器操作系统】服务器外挂存储ioerror分析及处理分享
更多银河麒麟操作系统产品及技术讨论,欢迎加入银河麒麟操作系统官方论坛 forum.kylinos.cn 了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:product.kylinos.cn 开发者专区:developer.kylinos.cn 文档中心&a…...
麒麟信安举办特种行业核心代理商中级技术认证培训班
近日,麒麟信安举办为期一周的特种行业核心代理商中级技术认证培训班,吸引了众多来自各地代理商公司的技术骨干踊跃参与。 此次培训班旨在赋能合作伙伴,助力其深入理解并熟练运用麒麟信安产品的核心优势,进一步提升在特种行业中的业…...
非对称加密:为什么RSA让“公开传密”成为可能
在1977年之前,加密世界遵循一个铁律:想要安全通信,必须先秘密交换密钥。无论是凯撒密码还是二战时的恩尼格玛机,都依赖发送方和接收方预先共享同一把“钥匙”。但RSA算法的出现颠覆了这一规则——它让陌生人可以在完全公开的环境下…...
阿里云ddos云防护服务器有哪些功能?ddos防御手段有哪些??
阿里云ddos云防护服务器有哪些功能?ddos防御手段有哪些?? DDoS(分布式拒绝服务)云防护服务器通过多种技术和策略来抵御大规模网络攻击,确保服务的高可用性。以下是其主要功能和防御手段的详细说明: 一、D…...
如何防止域名DNS被劫持?
防止域名DNS被劫持需要综合技术手段和管理措施,以下是一份详细的防护方案: --- ### **一、基础防护措施** 1. **选择可靠的域名注册商和DNS服务商** - 优先选择支持DNSSEC、提供多因素认证(MFA)的知名服务商(如Cl…...
桥隧坡灾害监测报警:用科技筑起生命安全的“智能防线”
.2024年,梅大高速茶阳路段高边坡塌方事件造成重大伤亡,举国痛心。这场悲剧再次敲响警钟:桥梁、隧道、边坡等高风险区域的实时监测与精准报警,已成为交通安全的生命线。如何用技术手段在灾害发生前“抢跑”,第一时间阻断…...
K8S常见问题汇总
一、 驱逐 master 节点上的所有 Pod 这会“清空”一个节点(包括 master)上的所有可驱逐的 Pod: kubectl drain <master-node-name> --ignore-daemonsets --delete-emptydir-data--ignore-daemonsets:保留 DaemonSet 类型的…...
ideal创建Springboot项目(Maven,yml)
以下是使用 IntelliJ IDEA 创建基于 Maven 的 Spring Boot 项目并使用 YAML 配置文件的详细步骤: 一、创建 Spring Boot 项目 启动项目创建向导 打开 IntelliJ IDEA,点击“File”->“New”->“Project”。 在弹出的“New Project”窗口中&#…...
解决:‘java‘ 不是内部或外部命令,也不是可运行的程序-Java环境变量配置(含JDK8、JDK21安装包一站式配置)
在使用命令行运行 .jar 文件时,很多用户会遇到如下错误提示: java 不是内部或外部命令,也不是可运行的程序或批处理文件。 这个报错表明系统无法识别 java 命令,通常是由于 Java 没有正确安装,或是系统环境变量没有配…...
android.app.Fragment和androidx.fragment:fragment的区别
android.app.Fragment 与 androidx.fragment.app.Fragment 的区别 这两个 Fragment 实现代表了 Android 碎片化开发的两个时代,以下是它们的核心区别: 一、起源与演变 android.app.Fragmentandroidx.fragment.app.Fragment引入时间Android 3.0 (API 1…...
OrangePi Zero 3学习笔记(Android篇)3 - 串口
目录 1. 找到串口号 2. 修改串口权限 3. 串口类 3.1 serialport.hpp 3.2 serialport.cpp 3.2.1 构造函数 3.2.2 Open函数 3.2.3 Close函数 3.2.4 Write函数 3.2.5 Read函数 3.2.6 SetFlowCtrl函数 4. 测试程序 5. 编译 6. 运行验证 除了默认的UART用于shell&…...
Node.js 技术原理分析系列9——Node.js addon一文通
Node.js 是一个开源的、跨平台的JavaScript运行时环境,它允许开发者在服务器端运行JavaScript代码。Node.js 是基于Chrome V8引擎构建的,专为高性能、高并发的网络应用而设计,广泛应用于构建服务器端应用程序、网络应用、命令行工具等。 本系…...
HBuilderX安卓真机运行安装失败解决汇总
前置方案 1. 确认USB调试和连接模式 (1)开启USB调试:进入手机设置 > 开发者选项 > 确保USB调试已开启(如无开发者选项,连续点击“版本号”激活)。 (2)连接模式:将…...
TensorFlow 2.x入门实战:从零基础到图像分类项目
TensorFlow 2.x入门实战:从零基础到图像分类项目 前言 TensorFlow是Google开发的开源机器学习框架,已成为深度学习领域的重要工具。TensorFlow 2.x版本相比1.x有了重大改进,更加易用且功能强大。本文将带你从零开始学习TensorFlow 2.x&…...
SpringBoot+Dubbo+Zookeeper实现分布式系统步骤
SpringBootDubboZookeeper实现分布式系统 一、分布式系统通俗解释二、环境准备(详细版)1. 软件版本2. 安装Zookeeper(单机模式) 三、完整项目结构(带详细注释)四、手把手代码实现步骤1:创建父工…...
数据中台-常用工具组件:DataX、Flink、Dolphin Scheduler、TensorFlow和PyTorch等
数据实施服务工具组件概览 数据中台的数据实施服务涵盖 数据采集、处理、调度、分析与应用 全流程,以下为关键工具组件及其作用: 工具类型核心功能典型应用场景DataX离线数据采集多源异构数据批量同步数据仓库ODS层数据导入Apache Flink实时计算引擎流…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】电商数据分析案例-9.2 流量转化漏斗分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 9.2 流量转化漏斗分析:从数据清洗到可视化全流程实战一、背景与目标二、数据准备与清洗2.1 数据来源与字段说明2.2 数据清洗步骤2.2.1 去除无效数据2.2.2 处理时…...
结合Splash与Scrapy:高效爬取动态JavaScript网站
在当今的Web开发中,JavaScript的广泛应用使得许多网站的内容无法通过传统的请求-响应模式直接获取。为了解决这个问题,Scrapy开发者经常需要集成像Splash这样的JavaScript渲染引擎。本文将详细介绍Splash JS引擎的工作原理,并探讨如何将其与S…...
[计算机科学#10]:早期的计算机编程方式
【核知坊】:释放青春想象,码动全新视野。 我们希望使用精简的信息传达知识的骨架,启发创造者开启创造之路!!! 内容摘要:1804年,为了在织布机上编织出丰富多彩的…...
JAVA:Spring Boot 集成 Lua 的技术博客
1、简述 在现代开发中,Lua 以其轻量级、高性能以及易嵌入的特点广泛用于脚本扩展、游戏开发以及配置处理场景。将 Lua 与 Spring Boot 集成,可以在 Java 项目中实现动态脚本功能,增强项目的灵活性和动态配置能力。 样例代码: https://gitee.com/lhdxhl/springboot-example…...
代码随想录算法训练营 Day40 动态规划Ⅷ 股票问题
动态规划 题目 121. 买卖股票的最佳时机 - 力扣(LeetCode) 使用二维 dp 数组表示 1. dp[i][0] 表示持有股票的最大金额,dp[i][1] 表示不持有股票的最大金额,表示盈利结果 2. 递推公式由前一天持有金额和是否买股票决定 决定是否…...
【已解决】WORD域相关问题;错误 未找到引用源;复制域出错;交叉引用域到底是个啥
(微软赶紧倒闭 所有交叉引用域,有两个状态:1.锁定。2.手动。可通过编辑->链接查看。 “锁定”状态域的能力: 1. 导出PDF格式稳定(【已解决】WORD导出PDF时,参考文献上标自动被取消/变为正常文本_word…...
小米 MiMo 开源:7B 参数凭什么 “叫板” AI行业巨头?
目录 一、技术革命的起点:小米AI战略的“破局者” 1.1 战略背景:从硬件厂商到AI基础设施提供商 1.2 团队揭秘:“天才少女”罗福莉与小米AI梦之队 二、技术架构解析:7B参数如何实现“推理跃迁” 2.1 核心技术原理 2.2 技术指…...
构建高可用性的LVS-DR群集:实现无缝的负载均衡与故障转移
目录 一、LVS-DR集群 1.LVS-DR工作原理 2.数据包流向分析 3.LVS-DR模式特点 二、直接路由模式(LVS-DR) 1.资源清单 2.配置负载调度器(lvs) 3.配置节点服务器(web1、web2) 4.测试LVS群集 5.使用NFS发布共享资源(nfs上) …...
低光图像增强新色彩空间HVI:技术突破与创新解析(HVI: ANewColor Space for Low-light Image Enhancement)
摘要 低光图像增强(LLIE)是计算机视觉领域的关键任务,旨在从受损的低光图像中恢复细节信息。针对现有方法在标准RGB(sRGB)空间易产生色偏与亮度伪影的问题,以及HSV色彩空间转换引发的红/黑噪声问题…...
Abaqus学习笔记
目录 Abaqus介绍 学习资源 编辑Abaqus/CAE abaqus下载安装 abaqus基本操作 Abaqus启动 新建模型 编辑 编辑修改界面背景 编辑编辑结果信息的显示与否 编辑计算结果信息字体设置 编辑允许多绘图状态 单位量纲 视图操作 事前说明 ODB文件 本构关系…...