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

网站建设本科毕业设计论文下载百度免费

网站建设本科毕业设计论文,下载百度免费,手机开网店用什么软件,iis8出现在网站首页目录 一、锁的使用场景 二、如何实现控制? 三、单台服务器使用锁的场景 四、分布式锁 五、Redis 实现分布式锁及存在问题 六、Redisson 实现分布式锁 七、定时任务+锁 一、锁的使用场景 1. 控制定时任务执行 定时任务多次执行浪费资源&#xff…

目录

一、锁的使用场景

二、如何实现控制?

三、单台服务器使用锁的场景

四、分布式锁

五、Redis 实现分布式锁及存在问题

六、Redisson 实现分布式锁

七、定时任务+锁


一、锁的使用场景

1. 控制定时任务执行

  • 定时任务多次执行浪费资源:多台服务器到同一时间都执行缓存预热
  • 脏数据:多台服务器重复插入数据

2. 买票场景

  • 只有一百张票,用户买票时判断剩余票的数量,还有剩余执行票数减一的操作
  • 只剩一张票了,此时多个用户来买票,判断票都是有剩余,但是第一个用户买完之后就没票了,其他用户也执行了票数减一的操作,出现超卖现象

3. 需求:控制定时任务 / 需要加锁的任务在同一时间只能有一台服务器执行

二、如何实现控制?

以定时任务为例

1. 分离定时任务程序和主程序,只在一台服务器运行定时任务=>成本太大

2. 写死配置,每个服务器都执行定时任务,但是只有 IP 符合配置的服务器才真实执行业务逻辑,其他的直接返回。成本最低;但是我们的 IP 可能是不固定的,把 IP 写的太死了

3. 动态配置,配置是可以轻松的、很方便地更新的(代码无需重启,项目无需重新部署),但是只有 IP 符合配置的服务器才真实执行业务逻辑。

  • 读取数据库中的配置

  • Redis

  • 配置中心(Nacos、Apollo、Spring Cloud Config)

  • 问题:服务器多了、IP 不可控还是很麻烦,还是要人工修改

4. 分布式锁:只有抢到锁的服务器才能执行业务逻辑

  • 坏处:增加成本
  • 好处:不用手动配置,多少个服务器都一样

三、单台服务器使用锁的场景

1. Java 实现同步锁:synchronized 关键字

2. 锁存在 JVM 中,每台 JVM 独立,不共享锁,多机部署锁会失效(多个线程都会获取到不同 JVM 中的同一名称的锁)

3. 单机就会存在单点故障

四、分布式锁

1. 为什么需要分布式锁?

  • 普通锁的缺点:JVM 机分配的锁在多台 Tomcat 中不共享,锁只对单个服务器有效
  • 加锁的重要性:资源有限 / 特定情况下只能有有限 / 唯一的线程获取到锁,执行操作
  • 分布式锁:多进程可见且并且互斥的锁

2. 如何实现分布式锁?

实现分布式锁的核心思想 / 怎么保证同一时间只有一台服务器能抢到锁?

  • 先来的人先把数据改成自己的标识(服务器 IP),后来的人发现标识已存在,就抢锁失败,继续等待
  • 等先来的人执行方法结束,把标识清空(释放锁),其他的人继续抢锁
  • MySQL 数据库:select for update 行级锁(最简单)
  • 乐观锁(实际上没有加锁):乐观锁认为线程安全问题只在少数情况下会发生,所以只要在数据更新时判断是否有其他线程修改了数据
  • Redis 实现互斥锁:基于内存,读写速度快
    • set nx ex:原子性、设置过期时间
    • lua 脚本:保证多条语句的原子性
  • Zookeeper

五、Redis 实现分布式锁及存在问题(误删锁)

1. set nx ex

2. 释放锁

  • 手动释放:del lock
  • 意外:服务器宕机,手动释放锁还未执行
  • 优化:设置过期时间,若未手动释放则等到过期时间到了就会自动释放锁

3. 误删锁

  • 线程 A 在执行时阻塞,过了锁的过期时间,锁自动释放
  • 线程 B 尝试获取锁,获取成功,执行业务
  • A 阻塞之后继续执行,执行结束,释放当前正在被线程 B 占有的锁
  • 线程 C 尝试获取锁,获取成功,执行业务
  • 出现线程 B 和线程 C 并发执行的情况

4. 解决误删锁

  • 判断当前锁的占有线程是不是本线程
  • 如果不是自己占有的锁,就不去释放(别人的锁)

5. 改进锁之后仍然存在问题:判断锁和释放锁的原子性问题

  • 判断锁时是自己正在占有锁
  • 判断锁标识后,执行释放锁之前,线程出现了阻塞,锁到了过期时间,自动释放
  • 其他线程尝试获取锁,获取成功
  • 阻塞之后执行释放锁,还是把别人的锁给释放了
  • 需要保证判断锁和释放锁操作的原子性:Lua 脚本

六、Redisson 实现分布式锁

Github:https://github.com/redisson/redisson

官网:Redisson: Easy Redis Java client with features of In-Memory Data Grid

1. 定义

  • Redisson 是一个在 Redis 基础上实现的 Java 驻内存数据网格
  • 提供了一系列分布式的 Java 常用对象,还提供了许多分布式服务(各种分布式锁的实现)

2. 自己编写 Redisson 的配置,创建 RedissonClient

  • 不推荐使用 spring-boot-starter 整合的 Redisson,版本迭代较快,容易发生冲突
  • 创建 config 对象,添加 Redis 配置:读取 application.yml 中的配置信息
  • 创建 Redisson 实例,返回 Redisson 客户端实例
/*** Redisson 配置* @author 乐小鑫* @version 1.0* @Date 2024-01-21-15:44*/
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedissonConfig {private String host;private String port;private String password;@Beanpublic RedissonClient getRedissonClient() {// 1. 创建配置Config config = new Config();String redisAddress = String.format("redis://%s:%s", host, port);config.useSingleServer().setAddress(redisAddress).setPassword(password).setDatabase(3);// 2. 创建 Redisson 客户端实例并返回RedissonClient redisson = Redisson.create(config);return redisson;}
}

3. 测试 Redisson 的功能实现

/*** @author 乐小鑫* @version 1.0* @Date 2024-01-21-15:53*/
@SpringBootTest
public class RedissonTest {@Resourceprivate RedissonClient redissonClient;@Testvoid test() {// listList<String> list = new ArrayList<>();list.add("ghost");System.out.println("List:" + list.get(0));RList<Object> rList = redissonClient.getList("test-list");rList.add("ghost");System.out.println("rList:" + rList.get(0));}
}

4. 看门狗机制的原理

  • 监听当前线程,当前线程没有执行结束就每十秒续期一次
  • 如果线程挂了(注意 Debug 模式时断点过久也会被当成服务器宕机来处理),看门狗机制失效,则不会续期
  • 参考文章:Redisson 分布式锁的watch dog自动续期机制_redisson续期-CSDN博客

七、定时任务+锁

1. getLock():获取 Redisson 的锁对象,需要指定锁的名称

2. tryLock():尝试获取锁(分布式锁),获取成功返回 true,可以指定重试获取锁的等待时间和锁的释放时间

  • waitTime 设置为 0:尝试获取锁获取失败,等待时间为 0,直接放弃获取锁(只尝试一次),因为这里是用户推荐列表的缓存预热定时任务,如果获取锁失败,说明已经有服务器去执行定时任务了,只要执行一次就好了,所以不用再去尝试获取锁

3. unlock():释放锁,放到 finally 语句块中执行,如果 try 语句块中的内容出现异常,也会释放锁,避免发生死锁的情况

/*** 缓存预热定时任务* @author 乐小鑫* @version 1.0*/
@Component
@Slf4j
public class PreCacheUser {@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate UserService userService;@Resourceprivate RedissonClient redissonClient;List<Long> mainUserList = Arrays.asList(3L);// 重要用户列表,为该列表的用户开启缓存预热@Scheduled(cron = "0 59 21 ? * * ")// 每天 21:59 执行定时任务进行用户数据缓存预热public void doPreCacheUser() {// 获取锁对象RLock lock = redissonClient.getLock("langhua:precachejob:doprecache:lock");try {if (lock.tryLock(0,30000L,TimeUnit.MILLISECONDS)) {log.info("get redisson lock" + Thread.currentThread().getId());// 查出用户存到 Redis 中for (Long userId : mainUserList) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();Page<User> userPage = userService.page(new Page<>(1, 20), queryWrapper);// 查询所有用户String key = String.format("langhua:user:recommend:%s", userId);ValueOperations valueOperations = redisTemplate.opsForValue();// 将查询出来的数据写入缓存try {valueOperations.set(key,userPage,24, TimeUnit.HOURS);} catch (Exception e) {log.error("redis key set error", e);}}}} catch (InterruptedException e) {log.error("redisson precache user error", e);} finally {// 释放锁log.info("redisson unlock" + Thread.currentThread().getId());lock.unlock();}}
}
http://www.hkea.cn/news/179383/

相关文章:

  • 1网站建设公司长沙网站到首页排名
  • 域名还在备案可以做网站吗seo培训班
  • 前程无忧网宁波网站建设类岗位北京网站快速排名优化
  • 如何优化网站内部链接站长工具站长之家
  • 阿里云网站建设的实训报告免费的自媒体一键发布平台
  • 关于加强网站建设的意见企业获客方式
  • 帮企业建设网站保密合同优化设计电子课本
  • 金山石化网站建设广告电话
  • 网站开发 前景网络推广代理
  • 温州整站推广咨询seo网站推广专员
  • 企业营销型网站团队百度seo排名优化教程
  • 安徽平台网站建设哪里好网络策划与营销
  • 做网站接广告赚钱么凡科建站和华为云哪个好
  • 成都网站建设科技公seo营销外包公司
  • 重庆有哪些做网站 小程序的百度搜索引擎的特点
  • 仁怀哪里可以做网站自动秒收录网
  • 重庆市建设局网站推广软件一键发送
  • 合肥网络推广网络运营网站seo诊断分析和优化方案
  • 网站优化公司免费咨询sem优化推广
  • 个人做网站赚钱么宁波seo推荐推广平台
  • 员工支付做网站的费用分录成都营销型网站制作
  • 专业做网站的公司邢台专业做网站关键词搜索优化
  • 电商网站建设方案模板杭州百度首页优化
  • 网站建设服务价格东莞市网站建设
  • 网站开发所需要的的环境佛山网络推广哪里好
  • php网站的优点关键路径
  • 电子政务与网站建设 总结湖南网站推广
  • 境外网站做网站涉黄互联网媒体广告公司
  • 河南做网站公司汉狮怎么做蛋糕
  • 哈 做网站网店代运营收费