为什么需要分布式系统锁
比如系统中的注册
需要先判断用户账号是否被注册 没有被注册则保存用户注册信息数据
在单系统情况下 可以这样做
String username = user.getUsername();
synchronized (username.intern()) {//防止多用户情况下 输入的相同账号都还未保存成功的情况下越过检查
if(userService.existUsername(username,"")){
mav.addObject("usernameMessage","用户名已存在");
return mav;
}
userService.save(user);
}
集群情况下可能是不同的服务器处理 无法阻止
分布式事务锁 底层借助memcached实现
/**
* 业务锁
*
* 通过 memcache 的 addCache获取锁
*
* @author 820381
*
*/
public class Lock {
/**
* 锁
* @param lockName
* @return true 成功/false 失败
*/
public static boolean lock(String lockName) {
return getLock(lockName, 0);
}
/**
* 解除锁
* @param lockName
* @return
*/
public static boolean unlock(String lockName) {
return CacheUtil.deleteKeyCache(lockName);
}
/**
* 锁,并在获得锁的时候执行回调,回调执行完成后,解除锁
* @param lockName 锁名
* @param call 回调函数
* @return BusinessRuntimeException: ExceptionCode.CMN_LOCK_FAILED
* @throws BusinessException
*/
public static <T> T lock(String lockName, Callback<T> call) throws BusinessException {
if(lock(lockName)) {
try {
return call.handle();
} finally {
unlock(lockName);
}
} else {
throw new BusinessException(ExceptionCode.CMN_LOCK_FAILED,
MessageFormat.format("连接超时[{0}]", lockName));
}
}
private static boolean getLock(String lockName, Integer count) {
boolean gotLock = false;
if(count > 1000) {
return gotLock;
}
while(true) {
gotLock = CacheUtil.addCache(lockName, true, null);
if(gotLock) {
return gotLock;
} else {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// 不处理异常睡眠异常
}
return getLock(lockName, ++count);
}
}
}
}
/**
*
* @ClassName: CacheUtil
* @Description: 缓存工具类
* @author Fanhy
* @date 2014-11-27 上午10:55:39
*
*/
public class CacheUtil {
/**
* 缓存客户端
*/
private static MemCachedClient memCachedClient;
/**
* 过期时间
*/
private String timeLenght;
/**
* 默认Key的超时时间(小于1000的值,除以1000以后都是0,即永不过期 )
*/
private static Date keyTimeOut;
@SuppressWarnings("unused")
private void init() {
keyTimeOut = new Date(Integer.parseInt(timeLenght));// 24小时缓存
}
/**
*
* @MethodName: getKeyCache
* @Description: 获取缓存
* @param keyName
* 缓存键
* @return 返回数据
*/
public static Object getKeyCache(String keyName) {
if (null != keyName) {
MemcachedItem item = memCachedClient.gets(keyName);
if (null != item) {
return item.getValue();
}
}
return null;
}
/**
*
* @MethodName: setCache
* @Description: 设置缓存
* @param keyName
* 缓存主键
* @param value
* 缓存数据
* @param date
* 过期时间(new Date(60000)过期时间是60秒)(如不设置默认缓存24小时)(不得超过30天)
*/
public static void setCache(String keyName, Object value, Date date) {
if (null != keyName && !"".equals(keyName)) {
if (null == date) {
memCachedClient.set(keyName, value, keyTimeOut);
} else {
memCachedClient.set(keyName, value, date);
}
}
}
/**
*
* @MethodName: setCache
* @Description: 设置缓存
* @param keyName
* 缓存主键
* @param value
* 缓存数据
*/
public static void setCache(String keyName, Object value) {
if (null != keyName && !"".equals(keyName)) {
memCachedClient.set(keyName, value, keyTimeOut);
}
}
/**
*
* @MethodName: deleteKeyCache
* @Description: 删除缓存
* @param keyName
* key名称
*/
public static boolean deleteKeyCache(String keyName) {
if (null != keyName && !"".equals(keyName)) {
return memCachedClient.delete(keyName);
}
return false;
}
public void setMemCachedClient(MemCachedClient memCachedClient) {
CacheUtil.memCachedClient = memCachedClient;
}
public void setTimeLenght(String timeLenght) {
this.timeLenght = timeLenght;
}
/**
*
* @MethodName: addCache
* @Description: 设置缓存不重复Key,暂时只用于分布式同步
* @param keyName
* @param value
* @param date
* @return void 返回类型
*/
public static boolean addCache(String keyName, Object value, Date date) {
boolean isTrue = false;
if (!StringUtils.isBlank(keyName)) {
if (null == date) {
Date dt = new Date();
date = DateUtils.addMinutes(dt, 3);
}
isTrue = memCachedClient.add(keyName, value, date);
}
return isTrue;
}
}
如何使用
@Aspect
@Component
public class LockAspect {
@Around("execution(* com.sfiec..*.*(..)) && @annotation(Lock)")
public Object around(final ProceedingJoinPoint point) throws Throwable {
String lockName = getLockName(point);
return com.sfiec.oms.common.Lock.lock(lockName, new Callback<Object>() {
@Override
public Object handle() throws BusinessException {
Object result;
try {
result = point.proceed();
} catch (Throwable e) {
if(e instanceof BusinessException) {
throw (BusinessException) e;
}
if(e instanceof BusinessRuntimeException) {
throw (BusinessRuntimeException) e;
}
throw new BusinessException("", e);
}
return result;
}
});
}
private String getLockName(ProceedingJoinPoint point) {
MethodSignature signature = MethodSignature.class.cast(point.getSignature());
Lock lock = signature.getMethod().getAnnotation(Lock.class);
// 不是自定义的锁标志的退出
if(lock == null) {
return null;
}
// 获取默认的锁
String lockName = lock.value();
// 不存在占位符,则直接返回
if(lockName.indexOf("${") == -1) {
return lockName;
}
// 获取占位符的内容
final Properties properties = new Properties();
String[] parameterNames = signature.getParameterNames();
Object[] args = point.getArgs();
for(int i = 0; i < parameterNames.length; i++) {
String name = parameterNames[i];
Object val = args[i];
if(isBaseDataType(val.getClass())) {
val = String.valueOf(val);
}
properties.put(name, val);
}
// TODO 如果存在 ${xx.xx} 属性,则使用反射获取内容
// 一般的 ${xxx},直接获取内容
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
String lockName2 = helper.replacePlaceholders(lockName, properties);
return lockName2;
}
/**
* 判断一个类是否为基本数据类型。
* @param clazz 要判断的类。
* @return true 表示为基本数据类型。
*/
@SuppressWarnings("rawtypes")
private static boolean isBaseDataType(Class clazz) {
return
(
clazz.equals(String.class) ||
clazz.equals(Integer.class)||
clazz.equals(Byte.class) ||
clazz.equals(Long.class) ||
clazz.equals(Double.class) ||
clazz.equals(Float.class) ||
clazz.equals(Character.class) ||
clazz.equals(Short.class) ||
clazz.equals(BigDecimal.class) ||
clazz.equals(BigInteger.class) ||
clazz.equals(Boolean.class) ||
clazz.equals(Date.class) ||
clazz.isPrimitive()
);
}
}
@Lock(CommonConstant.LOCK_REGISTER + " ${user.username}")
public boolean register(User user) {
if(userService.existUsername(username,"")){
mav.addObject("usernameMessage","用户名已存在");
return false;
}
userService.save(user);
return true;
}
相关推荐
《大规模分布式系统架构与设计实战》写到,分布式并行计算的基本原理解剖;分布式协调的实现,包括如何实现公共配置管理,如何实现分布式锁,如何实现集群管理等;分布式缓存的实现,包括如何提供完整的分布式缓存来...
用Redis实现分布式锁 与 实现任务队列
《大规模分布式系统架构与设计实战》从作者的实战经验出发,深入浅出地讲解了如何建立一个Hadoop那样的分布式系统,实现对多台计算机CPU、内存、硬盘的统一利用,从而获取强大计算能力去解决复杂问题。一般互联网...
在分布式系统中,分布锁是一个最基础的工具类。这篇文章主要介绍了用MySQL实现一个分布式锁,本文通过实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
1.3 分布式系统的定义 1.4 我们的模型 1.5 互连网络 1.6 应用与标准 1.7 范围 1.8 参考资料来源 参考文献 习题 第2章 分布式程序设计语言 2.1 分布式程序设计支持的需求 2.2 并行/分布式程序设计语言概述 ...
zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是集群的管理者。提供了文件系统和通知机制。...在开发项目的过程中,很多大型项目都是分布式部署的,那么我们现在使用zookeeper实现一个分布式锁。
系统的不断扩大,分布式锁是最基本的保障。与单机的多线程不一样的是,分布式跨多个机器。线程的共享变量无法跨机器。 为了保证一个在高并发存场景下只能被同一个线程操作,java并发处理提供ReentrantLock或...
介绍分布式锁的机制以及业务场景,系统介绍了分布式基础的特性,比较系统介绍了锁和事务的区别,对开源的分布式锁如redis实现分布式锁的机制方案进行阐述
Redis分布式锁----乐观锁的实现,以秒杀系统为例.rar
#资源达人分享计划#
现在面试,一般都会聊聊分布式系统这块的东西。通常面试官都会从服务框架(Spring Cloud、Dubbo)聊起,一路聊到分布式事务、分布式锁、ZooKeeper等知识。 所以咱们这篇文章就来聊聊分布式锁这块知识,具体的来看看...
Redis分布式锁在实现跨进程、跨机器的互斥访问时,虽功能强大,但也存在一些常见问题。这些问题主要源于网络延迟、系统时钟误差以及Redis自身的特性。 一个典型问题是锁的"死锁"现象,即因进程意外终止或网络故障,...
1.3 分布式系统的定义 1.4 我们的模型 1.5 互连网络 1.6 应用与标准 1.7 范围 1.8 参考资料来源 参考文献 习题 第2章 分布式程序设计语言 2.1 分布式程序设计支持的需求 2.2 并行/分布式程序设计语言概述 ...
zk只会对已经创建分布式锁的系统进行创建监听,所以性能消耗很小 2、运行出现错误 redis创建锁的节点如果挂了,那就只能等待超时才能释放锁 zk因为是创建临时的lockNode,所以挂了就释放了 3、操作 redis使用起来...
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。 分布式锁:当多个进程不在同一个系统中,用分布式...
PHP Redis分布式锁是一种通过Redis实现的锁机制,用于在分布式系统中控制对共享资源的访问。它通过Redis提供的原子性操作来确保在分布式环境下的并发访问的安全性。 适用人群: 开发分布式系统的工程师和架构师。 ...
#资源达人分享计划#
对高并发下的分布式系统访问共享资源提供分布式锁操作,使用者只需要加入简单的注解便可轻松对共享资源加分布式锁。 目前主要以Redis的形式实现分布式锁操作,后续扩展其他方式 mykit-lock-redis mykit-lock架构下以...
如何操作Redis和zookeeper实现分布式锁 在分布式场景下,有很多种情况都需要实现最终一致性。...分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序。在项目中,部署了多个tomca
数据同步:基于redis的分布式锁。 Web安全:实现XSS过滤和CSR过滤。 多系统交互:Dubbo,ActiveMQ多系统交互。 前后端分离:前端使用ajax访问后端的rest服务,后端返回json格式数据。页面用nginx反向代理访问。 支付...