一:前言

我在实际环境中遇到了这样一种问题,分布式生成id的问题!因为业务逻辑的问题,我有个生成id的方法,是根据业务标识+id当做唯一的值!

而uuid是递增生成的,从1开始一直递增,那么在同一台机器上运行代码,加上同步方法(synchronized),这个生成id的方法就是ok!

但是因为业务扩展或者说为了安全,项目运行在两台机器上,此时单个的同步方法(synchronized)就不能防止id的重复了!!!

要解决上面的这个问题,其他有如下解决办法!

(1):每台机器生产Id的代码,key+id 可以在前加上机器编号区分,key + id --- >机器唯一编号 + key + id

(2):使用数据库行锁(单个数据库的是时候),在需要插入id的表加上行锁,防止数据重复导致程序异常!

(3):使用分布式锁

二:分布式锁简介

网上有很多的讲解分布式锁的文章,但是细细分析很多的代码还是有很多的问题的,如下代码片段摘自博文:

https://my.oschina.net/91jason/blog/517996?p=1

http://blog.csdn.net/u010359884/article/details/50310387

public void lock(long timeout) {
long nano = System.nanoTime();
timeout *= 1000000;
final Random r = new Random();
try {
while ((System.nanoTime() - nano) < timeout) {
if (redisTemplate.getConnectionFactory().getConnection().setNX(key.getBytes(), LOCKED.getBytes())) {
redisTemplate.expire(key, EXPIRE, TimeUnit.SECONDS);
locked = true;
logger.debug("add RedisLock[" + key + "].");
break;
}
Thread.sleep(3, r.nextInt(500));
}
} catch (Exception e) {
}
}

博主也说了:如果长时间获取不到,就会获取锁失败,相当于没加锁!

这里还有可能发生其他问题:

(1)并发情况,expire主动释放锁的时候,可能释放的是别人的锁(不懂请查询资料)

(2)Redis服务挂掉,锁失败,相当于没加锁!

注:使用的时候要注意上面问题!!!

还有一种摘自博文:

http://www.cnblogs.com/0201zcr/p/5942748.html

这个博问分析的:

 while (timeout >= 0) {
long expires = System.currentTimeMillis() + expireMsecs + 1;
String expiresStr = String.valueOf(expires); //锁到期时间
if (this.setNX(lockKey, expiresStr)) {
// lock acquired
locked = true;
return true;
} String currentValueStr = this.get(lockKey); //redis里的时间
if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
// lock is expired String oldValueStr = this.getSet(lockKey, expiresStr);
//获取上一个锁到期时间,并设置现在的锁到期时间,
//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
//防止误删(覆盖,因为key是相同的)了他人的锁——这里达不到效果,这里值会被覆盖,但是因为什么相差了很少的时间,所以可以接受 //[分布式的情况下]:如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
// lock acquired
locked = true;
return true;
}
}
timeout -= DEFAULT_ACQUIRY_RESOLUTION_MILLIS; /*
延迟100 毫秒, 这里使用随机时间可能会好一点,可以防止饥饿进程的出现,即,当同时到达多个进程,
只会有一个进程获得锁,其他的都用同样的频率进行尝试,后面有来了一些进行,也以同样的频率申请锁,这将可能导致前面来的锁得不到满足.
使用随机的等待时间可以一定程度上保证公平性
*/
Thread.sleep(DEFAULT_ACQUIRY_RESOLUTION_MILLIS); }

这个相比第一个完善了误删除key的问题,但是要合理的设置超时时间,否则的话,也会使锁失效。

三:Redisson分布式锁的介绍和简单的使用

Redisson的介绍可以到:https://github.com/redisson/redisson/wiki/1.-概述 这里去了解!

我这里说一下使用时候要注意的问题:

1:文档里面说明了支持Redis 2.8以上版本,支持Java1.6+以上版本。根据自己的环境选择合适的版本!

2:2.8.1的redisson 需要使用 netty的jar包, 否则报错:

Hopper: java.lang.NoClassDefFoundError: io/netty/channel/EventLoopGroup。

3:2.8.1的redisson需要jackson 2.5+版本,否则报错bjectMapper.addMixIn method not fond。

我写了一个简单的例子,自己也做了一下测试,使用的Redis主从+哨兵模式!

demo的目录结构,具体的源码我放到github上面,地址:https://github.com/dufyun/kuyu/tree/master/redissondemo

注:这里一定要先安装Redis服务,如果没有安装Redis服务,请参考这篇:http://blog.csdn.net/u010648555/article/details/69944668

如果Redis服务安装到服务器上面,请修改代码中的Redis地址和端口!否则运行不起了!

运行这个类UUidGeneratorLockTest就可以看到效果!测试结果我也在readme.txt进行了总结!

如果在测试和学习的过程中有疑问,可以随时和我联系,也可以加左侧的群互相探讨!谢谢!

四:总结

这个时代,信息爆炸,各种技术博文之间互相复制,真正好的文章还是需要鉴别的!

我也要反思,自己之前也写过一些博文,也是遇到问题了,去网上搜一些解决方案,很多方案确实是理论上可以解决当前遇到的问题,当时去深究,就会发现很多的不完整性!

多思考,多测试!让代码能够更加高效和安全!

欢迎访问我的csdn博客,我们一同成长!

"不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!"

博客首页:http://blog.csdn.net/u010648555

Redisson分布式锁的简单使用的更多相关文章

  1. Redisson分布式锁实现

    转: Redisson分布式锁实现 2018年09月07日 15:30:32 校长我错了 阅读数:3303   转:分布式锁和Redisson实现 概述 分布式系统有一个著名的理论CAP,指在一个分布 ...

  2. Java使用Redisson分布式锁实现原理

    本篇文章摘自:https://www.jb51.net/article/149353.htm 由于时间有限,暂未验证 仅先做记录.有大家注意下哈(会尽快抽时间进行验证) 1. 基本用法 添加依赖 &l ...

  3. [转帖]SpringBoot集成redisson分布式锁

    SpringBoot集成redisson分布式锁 https://www.cnblogs.com/yangzhilong/p/7605807.html 前几天同事刚让增加上这一块东西. 百度查一下 啥 ...

  4. 又长又细,万字长文带你解读Redisson分布式锁的源码

    前言 上一篇文章写了Redis分布式锁的原理和缺陷,觉得有些不过瘾,只是简单的介绍了下Redisson这个框架,具体的原理什么的还没说过呢.趁年前项目忙的差不多了,反正闲着也是闲着,不如把Rediss ...

  5. Redisson 分布式锁实现之前置篇 → Redis 的发布/订阅 与 Lua

    开心一刻 我找了个女朋友,挺丑的那一种,她也知道自己丑,平常都不好意思和我一块出门 昨晚,我带她逛超市,听到有两个人在我们背后小声嘀咕:"看咱前面,想不到这么丑都有人要." 女朋友 ...

  6. Redisson 分布式锁实现之源码篇 → 为什么推荐用 Redisson 客户端

    开心一刻 一男人站在楼顶准备跳楼,楼下有个劝解员拿个喇叭准备劝解 劝解员:兄弟,别跳 跳楼人:我不想活了 劝解员:你想想你媳妇 跳楼人:媳妇跟人跑了 劝解员:你还有兄弟 跳楼人:就是跟我兄弟跑的 劝解 ...

  7. Redisson 分布式锁源码 09:RedLock 红锁的故事

    前言 RedLock 红锁,是分布式锁中必须要了解的一个概念. 所以本文会先介绍什么是 RedLock,当大家对 RedLock 有一个基本的了解.然后再看 Redisson 中是如何实现 RedLo ...

  8. Redisson 分布式锁源码 11:Semaphore 和 CountDownLatch

    前言 Redisson 除了提供了分布式锁之外,还额外提供了同步组件,Semaphore 和 CountDownLatch. Semaphore 意思就是在分布式场景下,只有 3 个凭证,也就意味着同 ...

  9. Redisson 分布式锁实战与 watch dog 机制解读

    Redisson 分布式锁实战与 watch dog 机制解读 目录 Redisson 分布式锁实战与 watch dog 机制解读 背景 普通的 Redis 分布式锁的缺陷 Redisson 提供的 ...

随机推荐

  1. 【NOIP2014】子矩阵

    这题如果按暴力做只有一半分,最大时间复杂度为O(C(16,8)*C(16,8)); 很容易算出超时: 我们可以发现如果直接dp会很难想,但是知道选哪几行去dp就很好写状态转移方程: dp[i][j]= ...

  2. 关于模式为singTask的activity的bundle问题

    1.问题描述 今天遇到一个问题,我的一个页面跳模式为singTask的activity时,bundle的值拿不到,我于是找了下,发现基础真的很重要; 2.原因 launchMode为singleTas ...

  3. 在ubantu上安装hive

    上次我们在ubantu上安装了hadoop,那我们现在再进一步,开始我们的学习之旅--hive板块吧! 第一步:准备! 软件: I.一个搭建好的hadoop环境 II.hive的bin文件(前往apa ...

  4. 32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用

    32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用 一丶32位(x86也称为80386)与8086(16位)汇编的区别 1.寄存器的改变 AX 变为 EAX  可以这样想,16位通 ...

  5. 聊聊并发-Java中的Copy-On-Write容器

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp78   聊聊并发-Java中的Copy-On-Write容器   Cop ...

  6. 在STEP7 TIA PORTAL中,设置模块的地址和设备名(Device name)

    assign device name, ip address for PROFINET componet in TIA Portal 方法1: PLC --> online & diag ...

  7. 嵌套ajax 页面卡死的问题

    问题:要一个AJAX中的回调函数中又进行了一个AJAX调用,并且这个AJAX是在一个循环调用的,不论设置async属性是true和false页面卡死. 解决方法:async属性都设为true,不用循环 ...

  8. 【★】深入BGP原理和思想【第…

    前言:学思科技术我想说,浅尝辄止,不是天才千万别深钻.和我研究高等数学一样,越深入就会发现越多的问题与不合理之处.尤其对于IT界,算法的最终解释权还是掌握在老外手中,所以对于有些细节,我们" ...

  9. MPLS LDP随堂笔记2

    前一天排错 Acl 1 匹配所有ospf的数据包 (目的 ospf建立邻居关系 传递路由条目) 2 放行UDP报文 让LDP邻居能互相收发HELLO包 4 放行TCP报文 让LDP邻居能够建立TCP会 ...

  10. 转: 【Java并发编程】之五:volatile变量修饰符—意料之外的问题(含代码)

    转载请注明出处:     volatile用处说明     在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...