Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-redlock

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-redlock

A simple Distributed Lock Manager for Redis, implemented with the RedLock algorithm, using either node-redis or ioredis clients.

  • 1.0.1
  • unpublished
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
11
increased by120%
Maintainers
1
Weekly downloads
 
Created
Source

node-redlock

A simple Distributed Lock Manager for Redis, implemented with the RedLock algorithm, using either node-redis or ioredis clients.

Installation

npm i node-redlock

Usage

import RedLock from "node-redlock"

//create a new lock manager
const lockManager = new RedLock([
	/**
	 * ioRedis clients, node-redis clients, or a mix.
	 * Clusters, instances, or a mix.
	 */
]);

//aquire a lock
const lock = await lockManager.aquire('myKey');

//the lock's key
lock.key;
//the lock's unique value
lock.uid;
//the lock's initial duration in milliseconds
lock.duration;
//the lock's max hold time in milliseconds across extends
lock.maxHoldTime;
//the lock's creation time in milliseconds
lock.startTime;
//the time remaining in milliseconds before the lock expires
lock.remainingTime;

//extend the lock
await lock.extend();
//release the lock (or just wait for it to expire).
await lock.release();

Settings

You can pass a settings object to the lock manager's constructor, these will be the default settings used across all new locks.

const lockManager = new RedLock([
	// ...
], {
	/** The duration of the lock in milliseconds, before the time to aquire is subtracted. Default `10000`. */
	duration: 10000,
	/** The number of times to retry aquiring a lock. Default `0`. */
	retryCount: 0,
	/** The max retry delay in milliseconds. A random time between this and zero will be selected. Default `500`. */
	retryDelay: 500,
	/** The maximum time in milliseconds that a lock should be held across extensions. Default `60000`. */
	maxHoldTime: 60000,
	/** The percent of the duration that should be used as drift, combined with `driftConstant`. Between 0 and 1. Default `0.001`. */
	driftFactor: 0.001,
	/** The fixed number of milliseconds to be used as drift, combined with `duration*driftFactor`. Default `5`. */
	driftConstant: 5,
});

You can also pass the same settings object to aquire, these will be used as the settings for only this lock.

// ...

const lock = await lockManager.aquire('myKey', {
	duration: 10000,
	retryCount: 0,
	retryDelay: 500,
	maxHoldTime: 60000,
	driftFactor: 0.001,
	driftConstant: 5,
});

Last, you can pass a subset of the settings object to extend, these will only be used during this extend. If you do not pass duration, the lock's original duration will be used. If you do not pass driftFactor or driftConstant the default values from the lock manager will be used.

// ...

await lock.extend({
	duration: 10000,
	driftFactor: 0.001,
	driftConstant: 5,
});

Errors

All errors are generated at the time of function execution, there are no events. A full list of error types can be seen in the RedLockError class.

The RedLock algorithm

A detailed overview of the RedLock algorithm can be read on the redis.io website. Quoting the site, a general overview is as follows:

In order to acquire the lock (on N instances, 5 here), the client performs the following operations:

  1. It gets the current time in milliseconds.
  2. It tries to acquire the lock in all the N instances sequentially, using the same key name and random value in all the instances. During step 2, when setting the lock in each instance, the client uses a timeout which is small compared to the total lock auto-release time in order to acquire it. For example if the auto-release time is 10 seconds, the timeout could be in the ~ 5-50 milliseconds range. This prevents the client from remaining blocked for a long time trying to talk with a Redis node which is down: if an instance is not available, we should try to talk with the next instance ASAP.
  3. The client computes how much time elapsed in order to acquire the lock, by subtracting from the current time the timestamp obtained in step 1. If and only if the client was able to acquire the lock in the majority of the instances (at least 3), and the total time elapsed to acquire the lock is less than lock validity time, the lock is considered acquired.
  4. If the lock was acquired, its validity time is considered to be the initial validity time minus the time elapsed, as computed in step 3.
  5. If the client failed to acquire the lock for some reason (either it was not able to lock N/2+1 instances or the validity time is negative), it will try to unlock all the instances (even the instances it believed it was not able to lock).

This library makes some minor changes to the algorithm, notably:

  1. Since this library uses clients that are provided to it, there is no good mechanism for implementing request timeouts as stated in step 2 of the algorithm. All requests are sent at the same time and awaited together via Promise.allSettled([ ...requests ]).
  2. As stated in the "Safety arguments" section, a drift factor and drift constant are also subtracted in step 3 of the algorithm. This has the effect of making the lock shorter (usually single milliseconds) in the name of safety.
  3. Lock extensions are added as described in the "Making the algorithm more reliable: Extending the lock" section.
  4. Auto retries are implemented, as described in the "Retry on failure" section.

Fault Tolerance

If absolute exclusivity is desired for a lock, even after an instance/node crash, extra settings are required for restarting/promoting instances/nodes. See the "Performance, crash-recovery and fsync" section of the RedLock documentation for more info.

Support

Currently this has only been tested on Node.js 16.3.x. More tests are to come and this section will be updated as I test them.

Keywords

FAQs

Package last updated on 19 Jan 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc