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

网站栏目标题网上推广

网站栏目标题,网上推广,wordpress禁止抓取分页,WordPress侧边按钮插件1 分布式锁 Java锁能保证一个JVM进程里多个线程交替使用资源。而分布式锁保证多个JVM进程有序交替使用资源,保证数据的完整性和一致性。 分布式锁要求 互斥。一个资源在某个时刻只能被一个线程访问。避免死锁。避免某个线程异常情况不释放资源,造成死锁…

1 分布式锁

Java锁能保证一个JVM进程里多个线程交替使用资源。而分布式锁保证多个JVM进程有序交替使用资源,保证数据的完整性和一致性。
分布式锁要求

  1. 互斥。一个资源在某个时刻只能被一个线程访问。
  2. 避免死锁。避免某个线程异常情况不释放资源,造成死锁。
  3. 可重入。
  4. 高可用。高性能。
  5. 非阻塞,没获取到锁直接返回失败。

2 实现

1 lua脚本

为了实现redis操作的原子性,使用lua脚本。为了方便改脚本,将脚本单独写在文件里。

-- 加锁脚本
if redis.call('setnx', KEYS[1], ARGV[1]) == 1 thenredis.call('pexpire', KEYS[1], ARGV[2]);return true;
elsereturn false;
end-- 解锁脚本
if redis.call('get', KEYS[1]) == ARGV[1] thenredis.call('del', KEYS[1]);return true;
elsereturn false;
end-- 更新锁脚本
if redis.call('get', KEYS[1]) == ARGV[1] thenredis.call('pexpire', KEYS[1], ARGV[2]);-- pexpire与expire的区别是:pexpire毫秒级,expire秒级return true;
elsereturn false;
end

将脚本装在Springboot容器管理的bean里。

@Configuration
public class RedisConfig {@Bean("lock")public RedisScript<Boolean> lockRedisScript() {DefaultRedisScript redisScript = new DefaultRedisScript<>();redisScript.setResultType(Boolean.class);redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/ratelimit/lock.lua")));return redisScript;}@Bean("unlock")public RedisScript<Boolean> unlockRedisScript() {DefaultRedisScript redisScript = new DefaultRedisScript<>();redisScript.setResultType(Boolean.class);redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/ratelimit/unlock.lua")));return redisScript;}@Bean("refresh")public RedisScript<Boolean> refreshRedisScript() {DefaultRedisScript redisScript = new DefaultRedisScript<>();redisScript.setResultType(Boolean.class);redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/ratelimit/refresh.lua")));return redisScript;}
}

redis分布式锁业务类

@Service
public class LockService {private static final long LOCK_EXPIRE = 30_000;private static final Logger LOGGER = LoggerFactory.getLogger(LockService.class);@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowired@Qualifier("lock")private RedisScript<Boolean> lockScript;@Autowired@Qualifier("unlock")private RedisScript<Boolean> unlockScript;@Autowired@Qualifier("refresh")private RedisScript<Boolean> refreshScript;public boolean lock(String key, String value) {boolean res = redisTemplate.execute(lockScript, List.of(key), value, LOCK_EXPIRE);if (res == false) {return false;}refresh(key, value);LOGGER.info("lock, key: {}, value: {}, res: {}", key, value, res);return res;}public boolean unlock(String key, String value) {Boolean res = redisTemplate.execute(unlockScript, List.of(key), value);LOGGER.info("unlock, key: {}, value: {}, res: {}", key, value, res);return res != null && Boolean.TRUE.equals(res);}private void refresh(String key, String value) {Thread t = new Thread(() -> {while (true) {redisTemplate.execute(refreshScript, List.of(key), value, LOCK_EXPIRE);try {Thread.sleep(LOCK_EXPIRE / 2);} catch (InterruptedException e) {e.printStackTrace();}LOGGER.info("refresh, current time: {}, key: {}, value: {}", System.currentTimeMillis(), key, value);}});t.setDaemon(true); // 守护线程t.start();}
}

测试类

@SpringBootTest(classes = DemoApplication.class)
public class LockServiceTest {@Autowiredprivate LockService service;private int count = 0;@Testpublic void test() throws Exception {List<CompletableFuture<Void>> taskList = new ArrayList<>();for (int threadIndex = 0; threadIndex < 10; threadIndex++) {CompletableFuture<Void> task = CompletableFuture.runAsync(() -> addCount());taskList.add(task);}CompletableFuture.allOf(taskList.toArray(new CompletableFuture[0])).join();}public void addCount() {String id = UUID.randomUUID().toString().replace("-", "");boolean tryLock = service.lock("account", id);while (!tryLock) {tryLock = service.lock("account", id);}for (int i = 0; i < 10_000; i++) {count++;}try {Thread.sleep(100_000);} catch (Exception e) {System.out.println(e);}for (int i = 0; i < 3; i++) {boolean releaseLock = service.unlock("account", id);if (releaseLock) {break;}}}
}

3 存在的问题

这个分布式锁实现了互斥,redis键映射资源,如果存在键,则资源正被某个线程持有。如果不存在键,则资源空闲。
避免死锁,靠的是设置reds键的过期时间,同时开启守护线程动态延长redis键的过期时间,直到该线程任务完结。
高性能。redis是内存数据库,性能很高。同时lua脚本使得redis以原子性更新锁状态,避免多次spirngboot与redis的网络IO。
非阻塞。lock()方法没有获取到锁立即返回false,不会阻塞当前线程。

没有实现可重入和高可用。高可用需要redis集群支持。

http://www.hkea.cn/news/906586/

相关文章:

  • 网站推广的方式包括哪些广西网站建设制作
  • 杭州营销网站建设东莞网站建设哪家公司好
  • 企业做营销型网站手机如何制作网页
  • 连云港网站关键词优化seo自学教程
  • 网站全站出售淘宝关键词排名怎么查询
  • 龙口市规划建设局网站查询收录
  • 学校网站建设注意什么东莞网站营销推广
  • 网站设计模板是什么百度网盘人工客服电话多少
  • wordpress文章收缩长春seo优化企业网络跃升
  • 网站地图调用希爱力双效片骗局
  • 珠海网站建设维护友情链接买卖代理
  • 武汉企业网站推广外包网络广告营销案例分析
  • 深圳哪里有做网站的汕头seo排名收费
  • 如何用腾讯云主机做网站株洲发布最新通告
  • 中国建设银行官网站下载信息流广告投放公司
  • 合肥建站平台网络平台推广是干什么
  • 黄冈工程建设标准造价信息网优化工作流程
  • 怎么做服装外贸网站怎么去推广一个产品
  • 和各大网站做视频的工作总结软件推广赚佣金渠道
  • asp.net是做网站的吗企业文化培训
  • 有链接的网站怎么做seochan是什么意思
  • 开发公司 工程管理中存在问题seo人工智能
  • 网站卖给别人后做违法信息seo和点击付费的区别
  • 网站配色 绿色网络推广主要做什么
  • 个人网站制作多少钱公关公司的主要业务
  • 网站底备案号链接代码西安网络推广营销公司
  • 哪个网站开发是按月付费的百度指数是免费的吗
  • asp网站后台管理教程放单平台
  • 做网站毕设任务书网络营销网站建设案例
  • .net 企业网站 模版关键词seo深圳