女生做网站前端设计师,智能锁网站建设关键词,哪个网站教做ppt模板,塔城建设局网站java分布式锁分布式锁
锁
锁的作用#xff1a;有限资源的情况下#xff0c;控制同一时间段#xff0c;只有某些线程#xff08;用户/服务器#xff09;能访问到资源。 锁在java中的实现#xff1a; synchronized关键字并发包的类 缺点#xff1a;只对单个的…java分布式锁分布式锁
锁
锁的作用有限资源的情况下控制同一时间段只有某些线程用户/服务器能访问到资源。 锁在java中的实现 synchronized关键字并发包的类 缺点只对单个的jvm有效
分布式锁
为什么实现分布式锁 有限资源的情况下控制同一段时间只有某些用户/服务器才能访问到资源单个锁只对单个jvm有效 分布锁实现核心思想先来server把数据改成自己的标识后来的人发现标识已经存在就等待 抢锁机制 同一时间只有一个服务器能抢到资源 Mysql数据库实现数据库中有一个字段标识锁哪个服务器先到达数据库就将此标识改为自己服务器的值下一个服务器查到达查看不为空就等待知道此上一个服务器用完将标识位改为空时方可用。 查select控制只有一个服务器在查1.select for update 行级锁2.乐观锁改update redis实现存标识。读写速度快支持setnxlua脚本实现 原理使用redis的setnx方法保证原子性质 setnx:set if not exist如果不存在则设置只有设置成功才会返回true否则返回false 注意1 用完锁之后要释放防止在释放之前服务器出现意外因此要设置过期时间注意2如果方法执行时间过长锁提前过期出现多个服务器同时执行。 续期redisson中提供续期机制原理监听当前线程默认过期时间是30s每10s续期一次补充到30s如果线程挂了则不会续期如果debug模式也会被当成服务器宕机。注意3连锁效应释放了其他server的锁 . 判断如果不是我的锁就不释放注意4释放锁的时候有可能先判断出是自己的锁但是这时候锁过期了会释放其他服务器/用户的锁 判断和释放的时候不允许其他任何的方法进入redis原子性操作。配合redislua脚本。 Zookeeper实现
控制定时任务的执行在同一时间只有一个服务器能执行 原因 浪费资源假设有1000台服务器同时工作脏数据 实现方式 分离定时任务把控制定时任务从主程序中拆开成本太大 配置写死配置每个服务器都执行定时任务但是只有ip符合配置的才真实执行业务逻辑其他的直接返回。 ☆动态配置这个配置是可以轻松的跟新的把配置写到数据库Redis配置中心NacosApollospring Cloud config问题如果服务器数据太多ip不可控制 分布式锁【只有抢到锁的服务器才能执行定时任务】
Reddisson实现分布式锁
Redisson是一个java操作Redis的客户端提供了大量的分布式数据集来简化对Redis的操作和使用可以让开发者像使用本地集合一样使用Redis完全感觉不到Redis的存在。 redisson官网redissonRedisson使用方法 支持springboot整合Rdisson写配置默认整合客户端。版本迭代太快只引入Redisson自己创建客户端 引入项目依赖Redisson类库 !--https://github.com/redisson/redisson#quick-start--dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.21.3/version/dependency新建redisson客户端/*** redisson配置*/
Configuration
ConfigurationProperties(prefix spring.redis)
Data
public class RedissonConfig {private String host;private String port;Beanpublic RedissonClient redissonClient(){// 1. 创建配置对象Config config new Config();String redisAddress String.format(redis://%s:%s,host,port);config.useSingleServer().setAddress(redisAddress).setDatabase(3);// 2. 创建实例RedissonClient redisson Redisson.create(config);return redisson;}
}使用锁实现缓存预热 waitTime 0 只抢一次/*** 缓存预热任务*/
Slf4j
public class PreCacheJob {Resourceprivate RedisTemplateString, Object redisTemplate;Resourceprivate UserService userService;Resourcepublic UserMapper userMapper;//重点用户private ListLong mainUserList Arrays.asList(1L);//引入redisson客户端Resourceprivate RedissonClient redissonClient;//每天执行预热推荐用户Scheduled(cron 0 31 19 * * ? )public void doCacheRecommendUser() {RLock lock redissonClient.getLock(yupao:precachejob:docache:lock);try {//waitTime:其他线程等待的时间因为我们缓存预热每天只做一次所以只要有一个线程拿到锁就//leaseTime锁过期时间if (lock.tryLock(0, 30000L, TimeUnit.MILLISECONDS)) {//是否拿到锁for (Long userId : mainUserList) {QueryWrapperUser queryWrapper new QueryWrapper();PageUser userPage userService.page(new Page(1, 20),queryWrapper);String redisKey String.format(yupao:user:recommend:%s, userId);ValueOperationsString, Object valueOperations redisTemplate.opsForValue();//写缓存try {valueOperations.set(redisKey, userPage, 30000,TimeUnit.MILLISECONDS);} catch (Exception e) {log.error(redis set key error, e);}}}} catch (InterruptedException e) {log.error(doCacheRecommendUser error,e);} finally {//释放自己的锁if (lock.isHeldByCurrentThread()) {//是否是当前线程System.out.println(unlock: Thread.currentThread().getId());lock.unlock();}}}
}