当前位置: 首页 > news >正文

临沂河东网站建设石家庄房产网上备案查询

临沂河东网站建设,石家庄房产网上备案查询,高端品牌网站设计欣赏,行者seo文章目录 ??Redis的分布式锁??误删问题 ??解决方法??代码实现 ??原子性问题 ??Lua脚本 ?利用Java代码调用Lua脚本改造分布式锁??代码实现 ??Redis的分布式锁 Redis的分布式锁是通过利用Redis的原子操作和特性来实现的。在分布式环境中#xff0c;多个应用…文章目录 ??Redis的分布式锁??误删问题 ??解决方法??代码实现 ??原子性问题 ??Lua脚本 ?利用Java代码调用Lua脚本改造分布式锁??代码实现 ??Redis的分布式锁 Redis的分布式锁是通过利用Redis的原子操作和特性来实现的。在分布式环境中多个应用程序或服务可能同时访问共享资源为了保证数据的一致性和避免冲突可以使用分布式锁来进行同步控制。 以下是一种常见的使用Redis实现分布式锁的方式 获取锁当一个应用程序需要获取锁时它可以通过执行以下操作在Redis中设置一个特定的键值对 SET lock_key unique_value NX PX lock_timeout 这里的lock_key是锁的唯一标识unique_value是唯一的值可以是随机生成的UUIDNX表示只有当键不存在时才会设置成功PX表示设置键的过期时间。通过设置过期时间即使获取锁的应用程序崩溃或异常退出锁也会在一段时间后自动释放避免出现死锁。 释放锁当应用程序完成对共享资源的操作后它可以通过执行以下操作释放锁 if GET lock_key unique_value then DELETE lock_key end 应用程序首先获取锁的当前值然后比较是否与自己持有的唯一值相等如果相等则删除该键表示释放锁。这样可以确保只有持有锁的应用程序才能释放锁避免误释放其他应用程序的锁。 需要注意的是分布式锁并不是绝对安全和可靠的。在高并发的环境中可能存在竞争条件和死锁等问题。因此在实际使用中需要考虑更复杂的场景和解决方案。 ??误删问题 遇到下面的情况的话会出现Redis分布式锁的误删问题 这种情况下。线程1首先获取锁但是发生了阻塞于是线程2拿到了执行权在线程2执行的过程中线程1苏醒了继续执行到后面线程1执行到了删除锁的操作此时就会把本应该属于线程2的锁删除这样子就造成了误删问题 ??解决方法 就是在每个线程释放锁的时候去判断一下当前这把锁是否属于自己如果属于自己则不进行锁的删除假设还是上边的情况线程1卡顿锁自动释放线程2进入到锁的内部执行逻辑此时线程1反应过来然后删除锁但是线程1一看当前这把锁不是属于自己于是不进行删除锁逻辑当线程2走到删除锁逻辑时如果没有卡过自动释放锁的时间点则判断当前这把锁是属于自己的于是删除这把锁。 ??代码实现 public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name name;this.stringRedisTemplate stringRedisTemplate;}private static final String KEY_PREFIX lock:;//使用uuid在获取锁的时候存入线程标识private static final String ID_PREFIX UUID.randomUUID().toString(true) -;Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标示String threadId ID_PREFIX Thread.currentThread().getId();// 获取锁Boolean success stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX name, threadId, timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success);//这里不能是return success否则 因为public后面的boolean是基本类型而Boolean是引用类型如果直接返回success是一个自动拆箱的过程可能回发生空指针异常}Overridepublic void unlock() {// 获取线程标示String threadId ID_PREFIX Thread.currentThread().getId();// 获取锁中的标示String id stringRedisTemplate.opsForValue().get(KEY_PREFIX name);// 判断标示是否一致if(threadId.equals(id)) {// 释放锁stringRedisTemplate.delete(KEY_PREFIX name);}} }??原子性问题 上面我们解决了误删问题 在误删问题的情况下遇到下面的情况的话会出现Redis分布式锁的原子性问题 这种情况下线程1先执行一段线程1先判断锁标识判断成功标识是属于线程1的后面就在线程1正准备删除锁释放的过程中突然线程1的锁过期了线程1发生阻塞 这个时候线程2开始执行在线程2执行过程中线程1阻塞结束了会执行删除锁的操作相当于判断锁标识并没有起到作用因为之前一句判断过了于是就把线程2的锁给删除掉了又一次发生了误删操作 这个时候线程3趁虚而入执行业务 这就是删锁时的原子性问题之所以有这个问题是因为判断锁标识和删除锁是2个动作这2个动作中间产生了阻塞 那么我们就要让这2个操作一起执行中间不能出现间隔 ??Lua脚本 Redis提供了Lua脚本功能在一个脚本中编写多条Redis命令确保多条命令执行时的原子性。Lua是一种编程语言它的基本语法大家可以参考网站https://www.runoob.com/lua/lua-tutorial.html这里重点介绍Redis提供的调用函数我们可以使用lua去操作redis又能保证他的原子性这样就可以实现拿锁比锁删锁是一个原子性动作了作为Java程序员这一块并不作一个简单要求并不需要大家过于精通只需要知道他有什么作用即可。 这里重点介绍Redis提供的调用函数语法如下 redis.call(命令名称, key, 其它参数, ...)例如我们要执行set name jack则脚本是这样 # 执行 set name jack redis.call(set, name, jack)例如我们要先执行set name Rose再执行get name则脚本如下 # 先执行 set name jack redis.call(set, name, Rose) # 再执行 get name local name redis.call(get, name) # 返回 return name写好脚本以后需要用Redis命令来调用脚本调用脚本的常见命令如下 例如我们要执行 redis.call(‘set’, ‘name’, ‘jack’) 这个脚本语法如下 如果脚本中的key、value不想写死可以作为参数传递。key类型参数会放入KEYS数组其它参数会放入ARGV数组在脚本中可以从KEYS和ARGV数组获取这些参数 利用Java代码调用Lua脚本改造分布式锁 接下来我们来回一下我们释放锁的逻辑 释放锁的业务流程是这样的 1、获取锁中的线程标示 2、判断是否与指定的标示当前线程标示一致 3、如果一致则释放锁删除 4、如果不一致则什么都不做 如果用Lua脚本来表示则是这样的 最终我们操作redis的拿锁比锁删锁的lua脚本就会变成这样 -- 这里的 KEYS[1] 就是锁的key这里的ARGV[1] 就是当前线程标示 -- 获取锁中的标示判断是否与当前线程标示一致 if (redis.call(GET, KEYS[1]) ARGV[1]) then-- 一致则删除锁return redis.call(DEL, KEYS[1]) end -- 不一致则直接返回 return 0lua脚本本身并不需要大家花费太多时间去研究只需要知道如何调用大致是什么意思即可所以在笔记中并不会详细的去解释这些lua表达式的含义。 我们的RedisTemplate中可以利用execute方法去执行lua脚本参数对应关系就如下图 ??代码实现 我们先写入lua这个脚本 -- 比较线程标示与锁中的标示是否一致 if(redis.call(get, KEYS[1]) ARGV[1]) then-- 释放锁 del keyreturn redis.call(del, KEYS[1]) end return 0然后我们来调用这个脚本 下面是完整代码 public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name name;this.stringRedisTemplate stringRedisTemplate;}private static final String KEY_PREFIX lock:;private static final String ID_PREFIX UUID.randomUUID().toString(true) -;private static final DefaultRedisScriptLong UNLOCK_SCRIPT;static {UNLOCK_SCRIPT new DefaultRedisScript();UNLOCK_SCRIPT.setLocation(new ClassPathResource(unlock.lua));UNLOCK_SCRIPT.setResultType(Long.class);}Overridepublic boolean tryLock(long timeoutSec) {// 获取线程标示String threadId ID_PREFIX Thread.currentThread().getId();// 获取锁Boolean success stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX name, threadId, timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success);//这里不能是return success否则 因为public后面的boolean是基本类型而Boolean是引用类型如果直接返回success是一个自动拆箱的过程可能回发生空指针异常}Overridepublic void unlock() {// 调用lua脚本stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX name),ID_PREFIX Thread.currentThread().getId());} }在技术的道路上我们不断探索、不断前行不断面对挑战、不断突破自我。科技的发展改变着世界而我们作为技术人员也在这个过程中书写着自己的篇章。让我们携手并进共同努力开创美好的未来愿我们在科技的征途上不断奋进创造出更加美好、更加智能的明天
http://www.w-s-a.com/news/432466/

相关文章:

  • 筑聘网windows优化大师自动安装
  • 龙华高端网站设计门户网站建设方案公司
  • 网站开发作用网站建设哪家专业
  • 网站设计报告总结南宁商城网站推广公司
  • 淘宝做店招的网站免费网站建设自助建站
  • 重庆工信部网站绵阳公司网站建设
  • 购物网站开发流程制作企业网页
  • 定州哪里可以做网站建设项目环境影响登记表备案系统网站
  • 网站建设费属于广告费小猪网站怎么做的
  • 国内优秀设计网站站长哈尔滨微网站建设
  • 如何建设一个优秀的电商网站沐风seo
  • 从零开始学网站建设知乎安防网站下载
  • 打开网站弹出qq应用软件有哪些
  • 温州网站建设seo网站 如何做 中英文切换
  • 聊城做网站的公司资讯信阳 网站建设
  • 天津市工程建设交易网站查汗国珠海 网页设计
  • 龙果学院大型网站稳定性建设汾阳做网站
  • 湖北 个人网站备案时间域名查询备案查询
  • 网站推广方式校园网站怎么建
  • 长沙seo网站排名怎么在百度发帖
  • 织梦贷款网站模板做印章网站
  • 彭州做网站上海百度网络推广
  • 广州网站搭建快速提升网站排名荧光字网站
  • 15年做那些网站能致富做seo是什么意思
  • 各电商网站的特点网站制作2007
  • 用html做一号店网站怎么做公众号注册平台官网
  • 做盈利网站怎么备案vs做网站如何调试
  • 嘉兴做营销型网站廊坊做网站外包
  • 双语网站模板常州做网站的公司
  • 广州市车管所网站建设全国做网站公司前十名