Распределенная блокировка транзакций с использованием Redis в node.js

Node.js Redis внешний интерфейс ZooKeeper
Распределенная блокировка транзакций с использованием Redis в node.js

В проектах узлов мы часто запускаем некоторые запланированные задачи, такие как регулярная отправка уведомлений, регулярная отправка электронных писем и т. д. Когда проект развертывается, мы часто развертываем несколько компьютеров и несколько экземпляров, что приводит к тому, что каждый экземпляр запускает одну и ту же задачу один раз, поэтому Нам нужна распределенная блокировка транзакций, чтобы гарантировать, что задача может быть запущена только один раз.

Распределенная блокировка транзакций

Существует множество способов реализации распределенных блокировок транзакций, которые можно условно разделить на следующие категории:

  • Реализация на основе базы данных
  • На основе кеша (redis, memcached)
  • На основе зоопарка

Для текущих нужд слишком хлопотно использовать блокировки базы данных, Zookeeper в настоящее время не используется в производстве, но он используется в проекте Redis, поэтому мы используем второй метод реализации.

redLock

Redis официально рекомендует соответствующее решениеRedlock, Реализация каждого языка указана в официальном документе, включая реализацию узла, следующим образом

Реализация redLock-узла

Он инкапсулирован в библиотеку, которая очень проста в использовании.

Конфигурация конфигурации

var client1 = require('redis').createClient(6379, 'redis1.example.com');
var client2 = require('redis').createClient(6379, 'redis2.example.com');
var client3 = require('redis').createClient(6379, 'redis3.example.com');
var Redlock = require('redlock');

var redlock = new Redlock(
	// you should have one client for each independent redis node
	// or cluster
	[client1, client2, client3],
	{
		// the expected clock drift; for more details
		// see http://redis.io/topics/distlock
		driftFactor: 0.01, // time in ms

		// the max number of times Redlock will attempt
		// to lock a resource before erroring
		retryCount:  10,

		// the time in ms between attempts
		retryDelay:  200, // time in ms

		// the max time in ms randomly added to retries
		// to improve performance under high contention
		// see https://www.awsarchitectureblog.com/2015/03/backoff.html
		retryJitter:  200 // time in ms
	}
);

Блокировка и разблокировка транзакций блокировки и снятие блокировки

// the string identifier for the resource you want to lock
var resource = 'locks:account:322456';

// the maximum amount of time you want the resource locked,
// keeping in mind that you can extend the lock up until
// the point when it expires
var ttl = 1000; // 锁的生存时间,在该时间内,若锁未释放,强行释放

redlock.lock(resource, ttl).then(function(lock) {

	// ...do something here...

	// unlock your resource when you are done
	return lock.unlock()
	.catch(function(err) {
		// we weren't able to reach redis; your lock will eventually
		// expire, but you probably want to log this error
		console.error(err);
	});
})

С помощью вышеуказанных методов мы можем реализовать распределенные блокировки транзакций.

возникшие проблемы

В ходе тестирования было обнаружено, что транзакция не была заблокирована.После проверки было обнаружено, что системное время двух машин было несогласованным, с разницей около 10 секунд (партнер по тестированию вручную корректировал время из-за других задачи), что привело к машине с более ранним временем. Сначала запустите задачу, машина с медленным временем, когда она переходит к получению блокировки, блокировка уже снята, поэтомуRedLock 建立在了 Time 是可信的模型上из. Рекомендовать статью здесьЯвляется ли Redis RedLock идеальным распределенным замком?очень хорошо объяснил

Увидел предложение в другом блоге

Теория распределенного CAP говорит нам, что «ни одна распределенная система не может одновременно удовлетворять согласованности, доступности и устойчивости к разделам и может одновременно удовлетворять не более чем двум из них».

Отличные, но несовершенные решения в сочетании с отличной эксплуатацией и обслуживанием определенно смогут решить большинство бизнес-задач.

И еще про таймаутttlЕсли значение слишком короткое, блокировка будет снята до завершения задачи. Наоборот, если время установки слишком велико, другим потокам, которые получают блокировку, возможно, придется подождать некоторое время. устанавливаться в соответствии с конкретным бизнес-сценарием.

резюме

Если Redis использует один модуль, в нем нет необходимости.redlockВ этой схеме используется непосредственноsetnxУстановите флаг, и все в порядке