A:分布式锁
B:防重复提交
一个通过redis 或 zookeeper 或 Ehcache 等集中式存储而实现的弱一致性分布式锁;以及在此基础上实现的防重复提交功能;
通过@EnableDistributedLock 注解开启分布式锁
通过@EnableResubmit 注解开启防重复提交功能
目前暂时只支持redis 和 Ehcache(非分布式); 后期可扩展至zookeeper;
弱一致性:依赖redis服务器的稳定性,如果加锁成功,对应reids服务器down掉,又重启,就有可能导致锁失效;
目前只支持spring boot项目
项目引用redis,并创建redis对应的bean:RedisTemplate或JedisCluster 任一bean即可
A: SpringBoot main class中引入注解:@EnableDistributedLock
@SpringBootApplication
@EnableDistributedLock //启动分布式锁(前提:项目中已经存在RedisTemplate或JedisCluster或org.ehcache.Manager 对应的bean)
public class App
{
public static void main( String[] args )
{
//启动项目
SpringApplication.run(App.class,args);
}
}
B: 业务代码
//业务bean中引用lockManager
@Autowired
LockManager lockManager;
//业务代码中使用lock(多例:一个lock只允许tryLock一次)
DistributedLock lock = lockManager.getLock();
try{
boolean locked = lock.tryLock(key,50); //key:锁(如:业务中的订单号); 50:过期时间(秒),本锁最长锁这么久,如果时间内没有解锁,则自动解锁
if(locked){
//... 业务
}
}finaly{
boolean unlocked = lock.unlock();
}
防重复提交
A: SpringBoot main class中引入注解:@EnableResubmit
@SpringBootApplication
@EnableResubmit(defaultResolver = HttpStatusResolver.class) //开户防重复提交(默认已经开户分布锁);defaultResolver指定了加锁失败后如何处理;如果不指定默认抛出异常
public class App
{
public static void main( String[] args )
{
//启动项目
SpringApplication.run(App.class,args);
}
}
B: 业务代码
业务方法上,使用@Resubmit注解;lockey:可以通过 spEL表达式获取方法参数中的值做为锁; expireSeconds 为锁过期时间,默认5秒;
@Resubmit(lockPrefix = "resubmit:pre:" ,lockKey = "#name",expireSeconds = 5)
public String resubmit(String name){
return "name";
}
C:重复提交处理 aop拦截到重复提交后,通过ResubmitResolver进行处理; 默认会创建三个Resolver bean:
默认使用的Resolver,可能通过@EnableResubmit(defaultResolver = {PrintResolver.class})指定
自定义Resolver: 实际业务中,除了使用统一的默认Resolver外,部分业务可能需要特殊的Resovler,此时可以由业务方开发自己的,实现了ResubmitResolver接口的Resolver;
@Resubmit(lockKey = "#name",resolver = PrintResolver.class)
特殊要求 ehcache做为锁缓存时,是非分布式锁,除非使用ehcache搭建分布式缓存; 主要用于测试和小项目; ehcache要求:创建一个Key class = String/Object/Serializable, value class = EhcacheValue,过期策略=EhcacheValueExpiryPolicy的缓存; 如:
CacheConfiguration distributedLockCfg = CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, //key对应的类型
EhcacheValue.class, //value对应的类型
ResourcePoolsBuilder.newResourcePoolsBuilder() //存储池配置(内存--磁盘)
.heap(1000L,EntryUnit.ENTRIES)//堆内存大小(条数)
.offheap(10L,MemoryUnit.MB) //堆外内存(容量)
.disk(50L,MemoryUnit.MB) //磁盘
)
//过期策略配置
.withExpiry(new EhcacheValueExpiryPolicy(Duration.ofSeconds(5),null,null))
.build();
// 2: CacheManager管理缓存
org.ehcache.CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
// 硬盘持久化地址
.with(CacheManagerBuilder.persistence(cachePath))
// 设置一个默认缓存配置
//.withCache("defaultCache", defaultConfig)
//设置一个分布式锁的cache(过期时间由元素值决定)
.withCache("distributedLockCache",distributedLockCfg)
//创建之后立即初始化
.build(true);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。