个人网站备案名称哪里有seo排名优化
目录
- 分布式锁
- 分布式锁实现的关键
- Redisson实现分布式锁
- 看门狗机制
分布式锁
为什么要使用分布式锁,或者分布式锁的使用场景?
定时任务。在分布式场景下,只控制一台服务器执行定时任务,这就需要分布式锁
要控制定时任务在同一时间只有 1 个服务器能执行,方案有哪些?
分离定时任务程序和主程序
,只在 1 个服务器运行定时任务。成本太大写死配置
。每个服务器都执行定时任务,但是只有 ip 符合配置的服务器才真实执行业务逻辑,其他的直接返回。成本最低;但是我们的 IP 可能是不固定的,会把 IP 写的太死了动态配置
,配置是可以轻松的、很方便地更新的(代码无需重启),但是只有 ip 符合配置的服务器才真实执行业务逻辑。问题:服务器多了、IP 不可控还是很麻烦,还是要人工修改- 配置写在数据库 、Redis、配置中心(Nacos、Apollo、Spring Cloud Config)
分布式锁
,只有抢到锁的服务器才能执行业务逻辑。坏处:增加成本;好处:不用手动配置,多少个服务器都一样。
锁
Java 实现锁:synchronized 关键字、并发包的类
问题:只对单个 JVM 有效
分布式锁实现的关键
抢锁机制
怎么保证同一时间只有 1 个服务器能抢到锁?
核心思想 就是:先来的人先把数据改成自己的标识(服务器 ip),后来的人发现标识已存在,就抢锁失败,继续等待。等先来的人执行方法结束,把标识清空,其他的人继续抢锁。
实现方式有:
- MySQL 数据库:select for update 行级锁(最简单)
- Redis 实现:内存数据库,读写速度快 。支持
setnx
、lua
脚本,比较方便我们实现分布式锁。
实现细节:
- 锁一定要加过期时间
- 用完锁要释放,释放的时候检查是否是自己的锁
- 如果方法执行时间过长,锁要能进行续约
- Redis 如果是集群(而不是只有一个 Redis),如果分布式锁的数据不同步怎么办? 使用红锁
Redisson实现分布式锁
Redisson 是一个 java 操作 Redis 的客户端,提供了大量的分布式数据集来简化对 Redis 的操作和使用,可以让开发者像使用本地集合一样使用 Redis,完全感知不到 Redis 的存在。
使用方式
- spring boot starter 引入(不推荐,版本迭代太快,容易冲突)链接
- 使用
Redisson
依赖 链接
RedissonConfig
/*** 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);// 使用单个Redis,没有开集群 useClusterServers() 设置地址和使用库config.useSingleServer().setAddress(redisAddress).setDatabase(3);// 2. 创建实例RedissonClient redisson = Redisson.create(config);return redisson;}
}
Redisson测试
@SpringBootTest
public class RedissonTest {@Resourceprivate RedissonClient redissonClient;@Testvoid test() {// list,数据存在本地 JVM 内存中List<String> list = new ArrayList<>();list.add("yupi");System.out.println("list:" + list.get(0));list.remove(0);// 数据存在 redis 的内存中RList<String> rList = redissonClient.getList("test-list");rList.add("yupi");System.out.println("rlist:" + rList.get(0));rList.remove(0);// mapMap<String, Integer> map = new HashMap<>();map.put("yupi", 10);map.get("yupi");RMap<Object, Object> map1 = redissonClient.getMap("test-map");// set// stack}
}
看门狗机制
Redisson会开一个监听线程,如果锁的方法还没执行完,就帮你重置 redis 锁的过期时间。
原理:
- 监听当前线程,默认过期时间是
30
秒,每10
秒续期一次(补到 30 秒) - 如果线程挂掉(注意 debug 模式也会被它当成服务器宕机),则不会续期