Производите только твердые сухие продукты
本文已收录在我的 GitHub 仓库,欢迎Star/fork:
Java-Interview-Tutorial
1 локальный замок
Обычно используемые блокировки, поставляемые с JDK, такие как синхронизация или блокировка, могут блокировать только текущий процесс и применимы только к службам с одной архитектурой. В сценариях распределенных мультисервисных экземпляров необходимо использовать распределенные блокировки.
2 Распределенный замок
2.1 Принцип распределенной блокировки
теория туалетной ямы
Вы можете отправиться в одно место одновременно, чтобы «занять яму»:
- занято, выполните логику
- в противном случае подождите, пока блокировка не будет снята
вращение за вращением
«Zhankeng» может обращаться к Redis, БД, любому месту, куда могут получить доступ все сервисы.
2.2 Эволюция распределенной блокировки
первый этап
// 占分布式锁,去redis占坑
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "111");
if(lock) {
//加锁成功... 执行业务
Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
redisTemplate . delete( key: "lock");//fHßti
return dataF romDb ;
} else {
// 加锁失败,重试。synchronized()
// 休眠100ms重试
// 自旋
return getCatalogJsonFromDbwithRedisLock();
}
сценарий проблемы
- setnx занимает яму, но бизнес-код ненормальный или программа падает во время выполнения, то есть логика блокировки не выполняется успешно, что приводит к взаимоблокировке
Решение: Установите автоматическое истечение срока действия блокировки, даже если она не будет удалена, она будет удалена автоматически.
второй этап
// 1. 占分布式锁,去redis占坑
Boolean lock = redisTemplate.opsForValue().setIfAbsent( "lock", "110")
if(lock) {
// 加锁成功...执行业务
// 突然断电
// 2. 设置过期时间
redisTemplate.expire("lock", timeout: 30, TimeUnit.SECONDS) ;
Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
//删除锁
redisTemplate. delete( key; "lock");
return dataFromDb;
} else {
// 加锁失败...重试。 synchronized ()
// 休眠100ms重试
// 自旋的方式
return getCatalogJsonF romDbWithRedisLock();
}
сценарий проблемы
- Setnx настроен, и я собираюсь установить время истечения срока действия, время простоя и взаимоблокировку.
Решение. Установка времени истечения и заполнителя должна быть атомарной операцией. Redis поддерживает использование команды setNxEx.
третий этап
// 1. 分布式锁占坑
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "110", 300, TimeUnit.SECONDS);
if(lock)(
// 加锁成功,执行业务
// 2. 设置过期时间,必须和加锁一起作为原子性操作
// redisTemplate. expire( "lock", з0, TimeUnit.SECONDS);
Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
// 删除锁
redisTemplate.delete( key: "lock")
return dataFromDb;
else {
// 加锁失败,重试
// 休眠100ms重试
// 自旋
return getCatalogJsonFromDbithRedislock()
}
четвертый этап
Уже есть lockvalue с UUID, но срок его действия истек! Другие получают блокировку и устанавливают новое значение, поэтому после if чужие блокировки удаляются! ! То есть снятие блокировки не является атомарной операцией.
Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
String lockValue = redisTemplate.opsForValue().get("lock");
if(uuid.equals(lockValue)) {
// 删除我自己的锁
redisTemplate.delete("lock");
}
сценарий проблемы
- Если это просто считается текущим значением, когда блокировка собирается быть удаленной, срок действия блокировки истек, и кто-то другой успешно установил новое значение. Это удаление является чужой блокировкой.
- решение
Блокировки удаления должны гарантировать атомарность. Используйте скрипты redis+Lua.
Этап пятый
- Убедитесь, что блокировка/разблокировка являются атомарными операциями.
String script =
"if redis.call('get', KEYS[1]) == ARGV[1]
then return redis.call('del', KEYS[1])
else
return 0
end";
Обеспечьте атомарность блокировки [занятость + время истечения срока действия] и удаление блокировки [решение + удаление]. Самое сложное, автоматическое обновление блокировки.
Суммировать
На самом деле, более хлопотным является автоматическое продление блокировки. Так что, будь то крупный завод или малая и средняя компания, мы напрямую выбираем Redisson для решения этих проблем! Не повторяйте создание колес, но также знайте, какие проблемы решает фреймворк, чтобы мы могли быстро устранять неполадки и локализовать возникающие проблемы. В следующей статье мы начнем редиссона, чтобы объяснить, как он продлевает замок~