Implementace distribuovaného zámku využívající Redis databáze


Redis databáze není jen tak ledasjaká obyčejná věc, dá se využít k implementaci distribuovaného zámku.

O jednu takovou jsem se pokusil v knihovně https://github.com/abelaska/jedis-lock.

Základem je využití vlastnosti funkce SETNX a tou je SET IF NOT EXISTS, tzn. že uloží hodnotu do požadovaného klíče pouze za podmínky, že klíč v daný moment v databázi neexistuje. Využívá se faktu, že Redis funkce jsou atomické.

Postup pro získání zámku je následující:

  1. SETNX lock.name <aktuální Unix timestamp + lock timeout + 1>, pokud je návratová hodnota 1 byl zámek úspěšně získán, v opačném případě se pokračuje dalším krokem.
  2. GET lock.name, provede se kontrola expirace zámku porovnáním hodnoty klíče zámku s aktuálním časem, tzn. že pokud je hodnota klíče zámku menší než aktuální čas je zámek expirovaný a pokračuje se dalším krokem. Pokud zámek expirovaný není pokračuje se krokem 4.
  3. GETSET lock.name <aktuální Unix timestamp + lock timeout + 1>, pokud funkce navrátí stejnou hodnotu jaká byla získaná v předchozím kroku, byl zámek úspěšně získán a zároveň nastaven nový korektní čas expirace. Pokud zámek nebyl získán pokračuje se následujícím krokem.
  4. Funkce počká 100 milisekund a poté pokračuje 1. krokem. Kroky se opakují dokud neuplyne timeout pro získání zámku (defaultní hodnota je 10 sekund).

Nevýhodné je tohle řešení ve chvíli kdy proces alokuje zámek a potom je ukončen aniž zámek uvolní. V tomto případě ostatní procesy zbytečně dlouho čekají než zámek expiruje. Jeden se s tím musí naučit žít.

Pokud používáte Apache Maven postačí do projektu doplnit novou závislost.

<dependency>
    <groupId>com.github.jedis-lock</groupId>
    <artifactId>jedis-lock</artifactId>
    <version>1.0.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

V příkladu je získán a následně uvolněn zámek s názvem lock.name. Timeout pro získání zámku nastaven na 10 sekund a expirace zámku na 30 sekund.

Jedis jedis = new Jedis("localhost");
JedisLock lock = new JedisLock(jedis, "lock.name", 10000, 30000);
lock.acquire();
try {
  // do some stuff
}
finally {
  lock.release();
}

A nakonec jsem využil https://oss.sonatype.org Maven repositář pro deploy knihovny do Maven Central repositáře. A to přesně podle postupu uvedeném na stránkách Sonatype OSS Maven Repository Usage Guide.

No a to je asi tak všechno. Enjoy 😉

Reklamy

Zanechat Odpověď

Vyplňte detaily níže nebo klikněte na ikonu pro přihlášení:

WordPress.com Logo

Komentujete pomocí vašeho WordPress.com účtu. Odhlásit / Změnit )

Twitter picture

Komentujete pomocí vašeho Twitter účtu. Odhlásit / Změnit )

Facebook photo

Komentujete pomocí vašeho Facebook účtu. Odhlásit / Změnit )

Google+ photo

Komentujete pomocí vašeho Google+ účtu. Odhlásit / Změnit )

Připojování k %s