- 简介
Sync是一款分布式场景下基于Redis的安全高效的线程同步组件,提供分布式可重入互斥锁、分布式可重入读写锁、分布式信号量。提供相应注解,使用简单,可与spring-boot无缝集成。
本组件已经上传到Maven中央库
- 环境要求
- JDK1.8及以上
- 技术支持
欢迎加我微信(zhong_xun_)入群交流。
通过引入Maven依赖和进行少量配置即可将Sync引入进你的系统。
Sync支持SpringBoot v2.x,也支持SpringBoot v1.x
<dependency>
<groupId>org.antframework.sync</groupId>
<artifactId>sync</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot版本}</version>
</dependency>
在application.properties或application.yaml中配置Redis和Sync
# 必填:命名空间(也可以通过ant.sync.namespace配置)
spring.application.name=customer #这里使用customer(会员系统)作为举例
# 必填:配置Redis(Cache采用的是spring-boot原生的Redis,所以原生的所有Redis配置都有效,以下以最简洁的配置举例)
# Redis单例模式
spring.redis.host=192.168.0.1
spring.redis.port=6379
# Redis集群模式
#spring.redis.cluster.nodes=192.168.0.1:6379,192.168.0.2:6379,192.168.0.3:6379
# Redis哨兵模式
#spring.redis.sentinel.master=mymaster
#spring.redis.sentinel.nodes=192.168.0.1:26379,192.168.0.2:26379,192.168.0.3:26379
# 以下配置均是选填配置,使用方一般使用默认配置即可,无需自定义配置
# 选填:是否启用Sync(true为启用,false为不启用;默认启用)
ant.sync.enable=true
# 选填:等待同步消息的最长时间(毫秒,默认为10秒)
ant.sync.max-wait-time=10000
# 选填:服务端类型(默认为redis)(sync还提供local模式,可以不依赖Redis,这种模式只对单个应用实例起效果,无法用在分布式场景)
ant.sync.server-type=redis
# 选填:发生异常时Redis中数据的存活时长(毫秒,默认为10分钟)
ant.sync.redis.live-time=600000
# 选填:@Semaphore注解使用的许可总数,通过ant.sync.semaphore.key-total-permits.${key}=${许可总数}的形式对key的许可总数进行配置
ant.sync.semaphore.key-total-permits.trade-123=100
ant.sync.semaphore.key-total-permits.trade-456=200
# 选填:@Lock、@ReadLock、@WriteLock、@Semaphore的AOP执行的优先级(默认为Ordered.LOWEST_PRECEDENCE - 10,默认比@Transactional先执行)
ant.sync.aop-order=2147483637
提供两种使用sync方式:
- 通过SyncContext使用
- 通过注解使用
使用sync前需先获取SyncContext:
@Autowired
private SyncContext syncContext;
// 传入锁的标识(比如:trade-123)就可获取对应的锁
Lock lock= syncContext.getLockContext().getLock("trade-123");
lock.lock(); // 加锁
try{
// TODO 具体业务逻辑
}finally {
lock.unlock(); // 解锁
}
- 读锁
// 传入锁的标识(比如:trade-123)就可获取对应的锁
ReadWriteLock rwLock=syncContext.getLockContext().getRWLock("trade-123");
rwLock.readLock().lock(); // 加读锁
try {
// TODO 具体业务逻辑
}finally {
rwLock.readLock().unlock(); // 解读锁
}
- 写锁
// 传入锁的标识(比如:trade-123)就可获取对应的锁
ReadWriteLock rwLock=syncContext.getLockContext().getRWLock("trade-123");
rwLock.writeLock().lock(); // 加写锁
try {
// TODO 具体业务逻辑
}finally {
rwLock.writeLock().unlock(); // 解写锁
}
// 传入信号量的标识(比如:trade-abc)就可获取对应的信号量,同时需指定分布式环境下总的可用许可数(比如:100)
Semaphore semaphore=syncContext.getSemaphoreContext().getSemaphore("trade-123", 100);
semaphore.acquire(5); // 获取5个许可
try {
// TODO 具体业务逻辑
}finally {
semaphore.release(5); // 释放5个许可
}
@org.springframework.stereotype.Service
public class TradeService {
@Lock(key = "#tradeId") // key是锁的标识。进入方法前加锁,退出方法后解锁
public Trade createTrade(String tradeId){
// TODO 具体业务逻辑
}
}
- 读锁
@org.springframework.stereotype.Service
public class TradeService {
@ReadLock(key = "#tradeId") // key是锁的标识。进入方法前加锁,退出方法后解锁
public Trade findTrade(String tradeId){
// TODO 具体业务逻辑
}
}
- 写锁
@org.springframework.stereotype.Service
public class TradeService {
@WriteLock(key = "#trade.tradeId") // key是锁的标识。进入方法前加锁,退出方法后解锁
public void updateTrade(Trade trade){
// TODO 具体业务逻辑
}
}
@org.springframework.stereotype.Service
public class TradeService {
// 总许可数通过ant.sync.semaphore.key-total-permits.trade-abc=100配置(这里指定分布式环境下trade-abc的总许可数为100)
@Semaphore(key = "#name", permits = 5) // key是信号量的标识。进入方法前获取5个许可,退出方法后释放5个许可
public void doBiz(String name){
// TODO 具体业务逻辑
}
}
Sync本身提供基于Redis和Local两种实现,同时具备灵活的扩展性。如果你想基于Zookeeper来实现,则可以实现org.antframework.sync.extension.Server接口;如果你想基于Redis实现,但又不想使用spring-data-redis提供的org.springframework.data.redis.connection.RedisConnectionFactory,则可以实现org.antframework.sync.extension.redis.extension.RedisExecutor接口。
扩展时可以参考:org.antframework.sync.extension.redis.RedisServer、org.antframework.sync.extension.local.LocalServer、org.antframework.sync.extension.redis.extension.springdataredis.SpringDataRedisExecutor