做一个积极的人

编码、改bug、提升自己

我有一个乐园,面向编程,春暖花开!

一:前言

我在实际环境中遇到了这样一种问题,分布式生成id的问题!因为业务逻辑的问题,我有个生成id的方法,是根据业务标识+id 当做唯一的值! 而uuid是递增生成的,从1开始一直递增,那么在同一台机器上运行代码,加上同步方法(synchronized),这个生成id的方法就是ok!

但是因为业务扩展或者说为了安全,项目运行在两台机器上,此时单个的同步方法(synchronized或者Lock)就不能防止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.-%E6%A6%82%E8%BF%B0 这里去了解!

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

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/learn-tech-collection/tree/master/redissondemo

注:这里一定要先安装Redis服务,如果没有安装Redis服务,请参考这篇:http://blog.csdn.net/u010648555/article/details/69944668 如果Redis服务安装到服务器上面,请修改代码中的Redis地址和端口!否则运行不起了!

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

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

四:总结

这个时代,信息爆炸,各种技术博文之间互相参考,真正的问题可能没有暴露出来,真正好的文章还是需要鉴别的!(我自己也会参考一些文章,但是我都会进行一些自己验证,一个是为准确性,一个加深自己的对知识的认识)

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

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

五:参考博文

Redis实现分布式锁全局锁—Redis客户端

Redisson中分布式锁RLock实现 分布式锁的几种实现方式


谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你每天开心愉快!


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

愿你我在人生的路上能都变成最好的自己,能够成为一个独挡一面的人

© 每天都在变得更好的阿飞云

多机器使用setnx 设置同一个key_Redisson分布式锁的简单使用相关推荐

  1. redis实现setnx,setex连用实现分布式锁

    redis实现分布式锁 1.主要命令: setnx setex 2.主要问题: 使用redis实现分布式锁,利用上面两个命令的特性.但是最重要的是锁要有过期时间,不然万一服务器宕机或者redis宕机, ...

  2. 关于几种分布式锁的简单介绍

    什么是分布式锁 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁.进程锁. 1.线程锁 主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同 ...

  3. 基于Redis的分布式锁的简单实现

    Redis官方给出两种思路 第一种:SET key value [EX seconds] [PX milliseconds] NX 第二种:SETNX+GETSET 首先,分别看一下这几个命令 SET ...

  4. Redis分布式锁的实现

    这里写目录标题 方案一:SETNX + EXPIRE 方案二:SETNX + value值是过期时间 方案三:SET的扩展命令(SET EX PX NX) 方案四:SET EX PX NX + 校验唯 ...

  5. Redis实现分布式锁(SETNX)

    目录 1.什么是分布式锁 2.分布式锁应具备的条件 3.为什么使用分布式锁 4.SETNX介绍 5.分布式锁实现 6.效果演示 7.Redisson分布式锁详解 8.Lua脚本实现可重入分布式锁 1. ...

  6. 场景应用:Redis使用setnx命令实现分布式锁

    文章目录 何时需要分布式锁? 如何实现分布式锁? 探究单节点锁:setnx命令 1. 加锁: 2. 解锁: 带来的问题 探究分布式锁:RedLock算法 补充:setnx命令学习 何时需要分布式锁? ...

  7. Redis分布式锁—SETNX+Lua脚本实现篇

    前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...

  8. redis setnx 分布式锁_Redis 分布式锁PHP

    Redis 分布式锁的作用 在单机环境下,有个秒杀商品的活动,在短时间内,服务器压力和流量会陡然上升.这个就会存在并发的问题.想要解决并发需要解决一下问题 1.提高系统吞吐率也就是qps 每秒处理的请 ...

  9. nx set 怎么实现的原子性_基于Redis的分布式锁实现

    前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...

最新文章

  1. 用c实现跨平台异常捕获机制
  2. Delphi 的消息机制浅探三
  3. UA MATH523A 实分析3 积分理论例题 集合的特征函数L2收敛的条件
  4. 【MySQL】mysql 远程连接111
  5. Yii Listview
  6. vue中watch数组或者对象
  7. opengl顶点数据传送和着色器处理(vao,vbo)
  8. OpenGL基础16:视角
  9. php合并两个有序链表,PHP如何实现合并两个有序链表为一个有序链表(代码)
  10. python opencv中的imwrite函数_python – OpenCV imwrite函数导致’undefined symbol’
  11. spring事件监听器系列二:@EventListener注解原理
  12. Linux下的编曲软件,MuseScore(免费作曲编曲软件) V3.0.1 Linux版
  13. 时间序列数据的特征提取
  14. 以衍复为例,聊聊当下的沪深300指数增强
  15. BAS:天牛须搜索智能优化算法
  16. 内存不能为read或written的解决方案
  17. 屏保:毛雷尔玫瑰屏保
  18. mysql注入单引号被转义_插入MySQL时转义PHP中的单引号[重复]
  19. vue中将水印加在页面的某一部分
  20. Linux文件及日志内容

热门文章

  1. python实现录音小程序 界面_小程序如何实现录音 播放功能
  2. python整数反转_敲代码学Python:力扣简单算法之整数反转
  3. MySQL学习(3)单表查询
  4. python什么软件开发好_python怎样才能学好?python软件开发什么
  5. 【技术干货+限时活动】openstack原理及在华为云中的应用
  6. ORACLE数据库导出导入数据
  7. 排名前16的Java工具类
  8. 《Python数据分析与挖掘实战》一1.2 从餐饮服务到数据挖掘
  9. windows 下 git 禁用 CRLF 转换 LF
  10. C4.5决策树算法概念学习