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

代做毕业设计网站 道路桥梁优化大师下载安装免费

代做毕业设计网站 道路桥梁,优化大师下载安装免费,东莞做网站公司有哪些,抖音官方推广渠道Java面试笔试面经、Java技术每天学习一点Java面试关注不迷路作者#xff1a;wangzaiplus来源#xff1a;https://www.jianshu.com/u/8cb4591440ca一、前言关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完… Java面试笔试面经、Java技术每天学习一点Java面试关注不迷路作者wangzaiplus来源https://www.jianshu.com/u/8cb4591440ca一、前言关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题), 但代码执行时间可能需要30s, 然后redis服务端10s后将锁删除, 此时, B线程恰好申请锁, redis服务端不存在该锁, 可以申请, 也执行了代码, 那么问题来了, A、B线程都同时获取到锁并执行业务逻辑, 这与分布式锁最基本的性质相违背: 在任意一个时刻, 只有一个客户端持有锁, 即独享为了解决这个问题, 本文将用完整的代码和测试用例进行验证, 希望能给小伙伴带来一点帮助二、准备工作压测工具jmeterhttps://pan.baidu.com/share/init?surlNN0c0tDYQjBTTPA-WTT3yg提取码: 8f2aredis-desktop-manager客户端https://pan.baidu.com/share/init?surlNoJtZZZOXsk45aQYtveWbQ提取码: 9bhfpostmanhttps://pan.baidu.com/share/init?surl28sGJk4zxoOknAd-47hE7w提取码: vfu7也可以直接官网下载, 我这边都整理到网盘了需要postman是因为我还没找到jmeter多开窗口的办法, 哈哈三、说明1、springmvc项目2、maven依赖                dependency            groupIdorg.springframework.datagroupId            artifactIdspring-data-redisartifactId            version1.6.5.RELEASEversion        dependency        dependency            groupIdredis.clientsgroupId            artifactIdjedisartifactId            version2.7.3version        dependency3、核心类分布式锁工具类: DistributedLock测试接口类: PcInformationServiceImpl锁延时守护线程类: PostponeTask四、实现思路先测试在不开启锁延时线程的情况下, A线程超时时间设为10s, 执行业务逻辑时间设为30s, 10s后, 调用接口, 查看是否能够获取到锁, 如果获取到, 说明存在线程安全性问题同上, 在加锁的同时, 开启锁延时线程, 调用接口, 查看是否能够获取到锁, 如果获取不到, 说明延时成功, 安全性问题解决五、实现1、版本01代码1)、DistributedLockpackage com.cn.pinliang.common.util;import com.cn.pinliang.common.thread.PostponeTask;import com.google.common.collect.Lists;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import redis.clients.jedis.Jedis;import java.io.Serializable;import java.util.Collections;Componentpublic class DistributedLock {    Autowired    private RedisTemplate redisTemplate;private static final Long RELEASE_SUCCESS  1L;private static final String LOCK_SUCCESS  OK;private static final String SET_IF_NOT_EXIST  NX;private static final String SET_WITH_EXPIRE_TIME  EX;// 解锁脚本(lua)private static final String RELEASE_LOCK_SCRIPT  if redis.call(get, KEYS[1])  ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end;/**     * 分布式锁     * param key     * param value     * param expireTime 单位: 秒     * return     */public boolean lock(String key, String value, long expireTime) {return redisTemplate.execute((RedisCallbackBoolean) redisConnection - {            Jedis jedis  (Jedis) redisConnection.getNativeConnection();            String result  jedis.set(key, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if (LOCK_SUCCESS.equals(result)) {return Boolean.TRUE;            }return Boolean.FALSE;        });    }/**     * 解锁     * param key     * param value     * return     */public Boolean unLock(String key, String value) {return redisTemplate.execute((RedisCallbackBoolean) redisConnection - {            Jedis jedis  (Jedis) redisConnection.getNativeConnection();            Object result  jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(key), Collections.singletonList(value));if (RELEASE_SUCCESS.equals(result)) {return Boolean.TRUE;            }return Boolean.FALSE;        });    }}说明: 就2个方法, 加锁解锁, 加锁使用jedis setnx方法, 解锁执行lua脚本, 都是原子性操作2)、PcInformationServiceImpl    public JsonResult add() throws Exception {        String key  add_information_lock;        String value  RandomUtil.produceStringAndNumber(10);        long expireTime  10L;        boolean lock  distributedLock.lock(key, value, expireTime);        String threadName  Thread.currentThread().getName();        if (lock) {            System.out.println(threadName   获得锁...............................);            Thread.sleep(30000);            distributedLock.unLock(key, value);            System.out.println(threadName   解锁了...............................);        } else {            System.out.println(threadName   未获取到锁...............................);            return JsonResult.fail(未获取到锁);        }        return JsonResult.succeed();    }说明: 测试类很简单, value随机生成, 保证唯一, 不会在超时情况下解锁其他客户端持有的锁3)、打开redis-desktop-manager客户端, 刷新缓存, 可以看到, 此时是没有add_information_lock的key的4)、启动jmeter, 调用接口测试设置5个线程同时访问, 在10s的超时时间内查看redis, add_information_lock存在, 多次调接口, 只有一个线程能够获取到锁redis1-4个请求, 都未获取到锁第5个请求, 获取到锁OK, 目前为止, 一切正常, 接下来测试10s之后, A仍在执行业务逻辑, 看别的线程是否能获取到锁可以看到, 操作成功, 说明A和B同时执行了这段本应该独享的代码, 需要优化。2、版本02代码1)、DistributedLockpackage com.cn.pinliang.common.util;import com.cn.pinliang.common.thread.PostponeTask;import com.google.common.collect.Lists;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import redis.clients.jedis.Jedis;import java.io.Serializable;import java.util.Collections;Componentpublic class DistributedLock {    Autowired    private RedisTemplate redisTemplate;private static final Long RELEASE_SUCCESS  1L;private static final Long POSTPONE_SUCCESS  1L;private static final String LOCK_SUCCESS  OK;private static final String SET_IF_NOT_EXIST  NX;private static final String SET_WITH_EXPIRE_TIME  EX;// 解锁脚本(lua)private static final String RELEASE_LOCK_SCRIPT  if redis.call(get, KEYS[1])  ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end;// 延时脚本private static final String POSTPONE_LOCK_SCRIPT  if redis.call(get, KEYS[1])  ARGV[1] then return redis.call(expire, KEYS[1], ARGV[2]) else return 0 end;/**     * 分布式锁     * param key     * param value     * param expireTime 单位: 秒     * return     */public boolean lock(String key, String value, long expireTime) {// 加锁Boolean locked  redisTemplate.execute((RedisCallbackBoolean) redisConnection - {            Jedis jedis  (Jedis) redisConnection.getNativeConnection();            String result  jedis.set(key, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if (LOCK_SUCCESS.equals(result)) {return Boolean.TRUE;            }return Boolean.FALSE;        });if (locked) {// 加锁成功, 启动一个延时线程, 防止业务逻辑未执行完毕就因锁超时而使锁释放            PostponeTask postponeTask  new PostponeTask(key, value, expireTime, this);            Thread thread  new Thread(postponeTask);            thread.setDaemon(Boolean.TRUE);            thread.start();        }return locked;    }/**     * 解锁     * param key     * param value     * return     */public Boolean unLock(String key, String value) {return redisTemplate.execute((RedisCallbackBoolean) redisConnection - {            Jedis jedis  (Jedis) redisConnection.getNativeConnection();            Object result  jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(key), Collections.singletonList(value));if (RELEASE_SUCCESS.equals(result)) {return Boolean.TRUE;            }return Boolean.FALSE;        });    }/**     * 锁延时     * param key     * param value     * param expireTime     * return     */public Boolean postpone(String key, String value, long expireTime) {return redisTemplate.execute((RedisCallbackBoolean) redisConnection - {            Jedis jedis  (Jedis) redisConnection.getNativeConnection();            Object result  jedis.eval(POSTPONE_LOCK_SCRIPT, Lists.newArrayList(key), Lists.newArrayList(value, String.valueOf(expireTime)));if (POSTPONE_SUCCESS.equals(result)) {return Boolean.TRUE;            }return Boolean.FALSE;        });    }}说明: 新增了锁延时方法, lua脚本, 自行脑补相关语法2)、PcInformationServiceImpl不需要改动3)、PostponeTaskpackage com.cn.pinliang.common.thread;import com.cn.pinliang.common.util.DistributedLock;public class PostponeTask implements Runnable {    private String key;    private String value;    private long expireTime;    private boolean isRunning;    private DistributedLock distributedLock;    public PostponeTask() {    }    public PostponeTask(String key, String value, long expireTime, DistributedLock distributedLock) {        this.key  key;        this.value  value;        this.expireTime  expireTime;        this.isRunning  Boolean.TRUE;        this.distributedLock  distributedLock;    }    Overridepublic void run() {        long waitTime  expireTime * 1000 * 2 / 3;// 线程等待多长时间后执行        while (isRunning) {            try {                Thread.sleep(waitTime);                if (distributedLock.postpone(key, value, expireTime)) {                    System.out.println(延时成功...........................................................);                } else {                    this.stop();                }            } catch (Exception e) {                e.printStackTrace();            }        }    }    private void stop() {        this.isRunning  Boolean.FALSE;    }}说明: 调用lock同时, 立即开启PostponeTask线程, 线程等待超时时间的2/3时间后, 开始执行锁延时代码, 如果延时成功, add_information_lock这个key会一直存在于redis服务端, 直到业务逻辑执行完毕, 因此在此过程中, 其他线程无法获取到锁, 也即保证了线程安全性下面是测试结果10s后, 查看redis服务端, add_information_lock仍存在, 说明延时成功此时用postman再次请求, 发现获取不到锁看一下控制台打印A线程在19:09:11获取到锁, 在10 * 2 / 3 6s后进行延时, 成功, 保证了业务逻辑未执行完毕的情况下不会释放锁A线程执行完毕, 锁释放, 其他线程又可以竞争锁OK, 目前为止, 解决了锁超时而业务逻辑仍在执行的锁冲突问题, 还很简陋, 而最严谨的方式还是使用官方的 Redlock 算法实现, 其中 Java 包推荐使用 redisson, 思路差不多其实, 都是在快要超时时续期, 以保证业务逻辑未执行完毕不会有其他客户端持有锁
http://www.huolong8.cn/news/4463/

相关文章:

  • 网站建设的客户网站备案怎么弄
  • 网站内网页标题对百度排名福彩网网站建设方案
  • 北京市地铁建设公司网站移动路由器做网站服务器
  • 特色专业建设网站团购商城网站建设方案
  • 南坪做网站南京网站制作步骤
  • 鹤庆县公路建设网站pc网站怎么做自适应
  • 杭州做微信网站软件公司网站开发能干什么
  • 做网站用到什么技术wordpress 4.4漏洞
  • 网站制作外包价格做购物网站骗人
  • 小木桥路建设工程招投标网站页面设计要怎么做
  • 晋中网站建设电话临沂森佳木业有限公司
  • 食品网站应该怎么做哪个网站做长图免费转高清
  • 四川住房城乡建设厅网站首页贵阳seo网站推广
  • 最新网站制作seo综合查询接口
  • 服务佳的网站建设遵义做网站哪个公司最好
  • 网站建设企业服务商百家号如何给网站做推广
  • 栾川网站开发网站seo分析报告案例
  • 建设网站如何加入搜索老总办公室装修风格
  • 网站内链建设门户网站建设 增强责任意识
  • 网站侧边栏菜单广东平台网站建设制作
  • 站长工具百度百科房屋装修效果图app有哪些
  • 网站建设方案书1500字wordpress协会主题
  • 网站处于建设中会显示什么英文c2c网站功能模块设计
  • wordpress图片站点云南省人防工程建设网站
  • 企业自助建站金融 网站 源码
  • 网上商城建设网站常规seo优化步骤
  • 有什么网站是python做的网站dede后台
  • 注册个人公司流程及费用内蒙古seo
  • 做网站需要画原型图么网站建设改变某个表格大小
  • 做网站做得好的公司有哪些网站上的flv视频看不了