Obsah
1. Využití Redisu z jazyka Clojure pomocí knihovny Carmine (dokončení)
3. Základní operace s množinami prováděné z knihovny Carmine
4. Množinové operace: sjednocení, průnik, rozdíl
5. Množinové operace prováděné z jazyka Clojure
7. Práce s mapami v jazyku Clojure
8. Množiny s ohodnocenými prvky (uspořádané množiny)
9. Uspořádané množiny a jazyk Clojure
10. Komunikační strategie publish-subscribe
11. Program konzumující zprávy (subscriber)
12. Program produkující zprávy (publisher)
13. Použití front pro komunikaci
14. Implementace workera přijímacího úkoly přes frontu
15. Klient vytvářející zprávy pro workery
16. Seznam popsaných maker a funkcí knihovny Carmine
17. Repositář s demonstračními příklady
18. Předchozí články o systému Redis
19. Odkazy na předchozí části seriálu o programovacím jazyku Clojure
1. Využití Redisu z jazyka Clojure pomocí knihovny Carmine (dokončení)
V úvodním článku jsme se seznámili s tím, jakým způsobem je možné vyvinout aplikace v programovacím jazyku Clojure, které komunikují s databází Redis. Pro tento účel jsme použili knihovnu Carmine. Prozatím víme, jakým způsobem se do Redisu ukládají jednotlivé hodnoty pod určitým klíčem (přičemž hodnotou může být řetězec, ale i celý serializovaný objekt). Taktéž jsme si ukázali základní operace se seznamy, které mohou být ve skutečnosti použity i ve funkci zásobníků popř. front. Dnes si popíšeme další datové typy podporované Redisem, zejména mapy (asociativní pole), množiny a takzvané uspořádané množiny. Ve druhé části článku si na několika demonstračních příkladech ukážeme způsob použití komunikačních strategií publish-subscribe i využití front zpráv (queue).
2. Množiny
Kromě datových typů popsaných minule (tedy řetězců a seznamů, přičemž řetězce mohou ve skutečnosti obsahovat čísla či serializované objekty) lze v Redisu pracovat i s dalšími datovými typy (a každý z nich se pochopitelně hodí pro jiné účely). Třetím datovým typem, s nímž je možné v Redisu pracovat a s nímž se ve stručnosti seznámíme, jsou množiny (sets). Každá množina může obsahovat až 232-1 prvků, což je stejná maximální kapacita prvků, jako u seznamů. Prvky se do množiny přidávají příkazem sadd (neboli set add), přičemž je nutné uvést jak jméno (identifikátor) množiny, tak i hodnotu vkládaného prvku. V případě, že množina daného jména neexistuje, je prvním příkazem sadd vytvořena:
127.0.0.1:6379> sadd s "foo" (integer) 1 127.0.0.1:6379> sadd s "bar" (integer) 1 127.0.0.1:6379> sadd s "baz" (integer) 1
Celkový počet prvků uložených v množině získáme příkazem scard, seznam všech prvků pak příkazem smembers:
127.0.0.1:6379> scard s (integer) 3 127.0.0.1:6379> smembers s 1) "bar" 2) "baz" 3) "foo"
Test, jestli množina obsahuje nějaký prvek, zajistí příkaz sismember, který vrací numerickou hodnotu 0 nebo 1:
127.0.0.1:6379> sismember s "foo" (integer) 1 127.0.0.1:6379> sismember s "xyzzy" (integer) 0
Odstranění prvku z množiny zajistí příkaz srem, který navíc vrátí příznak, zda byl prvek odstraněn (tj. zda vůbec v množině figuroval):
127.0.0.1:6379> srem s "foo" (integer) 1 127.0.0.1:6379> sismember s "foo" (integer) 0 127.0.0.1:6379> smembers s 1) "bar" 2) "baz"
Vzhledem k tomu, že se jedná o skutečné množiny, je ošetřen i případ, kdy se do množiny vkládá více stejných prvků:
127.0.0.1:6379> sadd mnozina 1 (integer) 1 127.0.0.1:6379> sadd mnozina 2 (integer) 1 127.0.0.1:6379> sadd mnozina 1 (integer) 0
3. Základní operace s množinami prováděné z knihovny Carmine
Všechny operace s množinami, které jsme si popsali ve druhé kapitole jsou pochopitelně podporovány i knihovnou Carmine. Ukázány jsou v následujícím demonstračním příkladu. Povšimněte si, že se (do značné míry) jedná o idiomatický kód programovacího jazyka Clojure, protože namísto textových literálů používáme „keywords“, tedy symboly, které jsou ve všech jmenných prostorech unikátní a jsou interně reprezentovány referencí a nikoli hodnotou (tedy nezáleží na délce symbolu):
(ns carmine8.core (:require [taoensso.carmine :as carmine :refer (wcar)])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Working with two sets") (println "Set s1") (println (wcar* (carmine/sadd :s1 :a) (carmine/sadd :s1 :b) (carmine/sadd :s1 :c) (carmine/sadd :s1 :d) (carmine/smembers :s1) (carmine/scard :s1))) (println "Set s2") (println (wcar* (carmine/sadd :s2 :c :d :e :f) (carmine/smembers :s2) (carmine/scard :s1))) (println "Done"))
Po spuštění tohoto příkladu se mj. vypíšou i dva vektory:
Working with two sets Set s1 [1 1 1 1 [c d b a] 4] Set s2 [4 [f e c d] 4] Done
První vektor obsahuje postupně výsledek čtyř operací sadd, následně prvky množiny :s1 a konečně počet prvků množiny. Druhý vektor obsahuje výsledek operace sadd, která vložila čtyři prvky, následně prvky množiny :s2 a nakonec taktéž počet prvků této množiny.
4. Množinové operace: sjednocení, průnik, rozdíl
Systém Redis podporuje provádění základních množinových operací – tedy konkrétně sjednocení, průniku a rozdílu. Tyto operace jsou vyvolány příkazy nazvanými sunion, sunionstore, sinter, sinterstore, sdiff a sdiffstore.
Před ukázkou základního způsobu použití těchto operací si vytvoříme dvě množiny s identifikátory s1 a s2.
Naplnění množiny s1 čtyřmi prvky:
127.0.0.1:6379> sadd s1 1 (integer) 1 127.0.0.1:6379> sadd s1 2 (integer) 1 127.0.0.1:6379> sadd s1 3 (integer) 1 127.0.0.1:6379> sadd s1 4 (integer) 1
Naplnění množiny s2 taktéž čtyřmi prvky (ovšem částečně odlišnými od množiny s1):
127.0.0.1:6379> sadd s2 3 (integer) 1 127.0.0.1:6379> sadd s2 4 (integer) 1 127.0.0.1:6379> sadd s2 5 (integer) 1 127.0.0.1:6379> sadd s2 6 (integer) 1
Pro jistotu si vypíšeme aktuální obsah obou množin:
127.0.0.1:6379> smembers s1 1) "1" 2) "2" 3) "3" 4) "4" 127.0.0.1:6379> smembers s2 1) "3" 2) "4" 3) "5" 4) "6"
Příkazem sunionstore vytvoříme novou množinu, která bude sjednocením obou množin zdrojových (union). Následně zkontrolujeme výsledek:
127.0.0.1:6379> sunionstore s3 s1 s2 (integer) 6 127.0.0.1:6379> smembers s3 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 6) "6"
Podobně je možné příkazem sinterstore vytvořit novou množinu s využitím operace průniku (intersection):
127.0.0.1:6379> sinterstore s4 s1 s2 (integer) 2 127.0.0.1:6379> smembers s4 1) "3" 2) "4"
Poslední podporovanou operací je rozdíl množin (difference). Tato operace není komutativní, takže je pochopitelně výsledek jiný při provedení rozdílu s1\s2 a s2\s1:
127.0.0.1:6379> sdiffstore s5 s1 s2 (integer) 2 127.0.0.1:6379> smembers s5 1) "1" 2) "2" 127.0.0.1:6379> sdiffstore s6 s2 s1 (integer) 2 127.0.0.1:6379> smembers s6 1) "5" 2) "6"
5. Množinové operace prováděné z jazyka Clojure
Opět platí, že všechny výše popsané a otestované množinové operace můžeme provádět z programovacího jazyka Clojure s využitím knihovny Carmine. Ukažme si nejdříve operace, u nichž se výsledek ukládá zpět do Redisu do nové množiny, tedy operace, jejichž jméno končí na „store“:
(ns carmine9.core (:require [taoensso.carmine :as carmine :refer (wcar)])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Working with two sets") (println "Fill in sets s1 and s2") (println (wcar* (carmine/srem :s1 :a :b :c :d :e :f) (carmine/srem :s2 :a :b :c :d :e :f) (carmine/sadd :s1 :a :b :c :d) (carmine/sadd :s2 :c :d :e :f) (carmine/smembers :s1) (carmine/smembers :s2))) (println "Set operations") (println "union") (println (wcar* (carmine/sunionstore :s3 :s1 :s2) (carmine/smembers :s3))) (println "intersection") (println (wcar* (carmine/sinterstore :s4 :s1 :s2) (carmine/smembers :s4))) (println "diff") (println (wcar* (carmine/sdiffstore :s5 :s1 :s2) (carmine/smembers :s5) (carmine/sdiffstore :s6 :s2 :s1) (carmine/smembers :s6))) (println "Done"))
Po spuštění tohoto demonstračního příkladu získáme sérii vektorů, přičemž u zvýrazněných vektorů je zobrazen počet prvků ve výsledné množině, za nímž následuje seznam těchto prvků:
Working with two sets Fill in sets s1 and s2 [0 0 4 4 [d b a c] [f d e c]] Set operations union [6 [c d b f a e]] intersection [2 [d c]] diff [2 [b a] 2 [f e]] Done
Podobným způsobem je možné použít i množinové operace, jejichž výsledkem je množina vrácená uživateli (ale neukládaná zpět do Redisu):
(ns carmineA.core (:require [taoensso.carmine :as carmine :refer (wcar)])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Working with two sets") (println "Fill in sets s1 and s2") (println (wcar* (carmine/srem :s1 :a :b :c :d :e :f) (carmine/srem :s2 :a :b :c :d :e :f) (carmine/sadd :s1 :a :b :c :d) (carmine/sadd :s2 :c :d :e :f) (carmine/smembers :s1) (carmine/smembers :s2))) (println "Set operations") (println "union") (println (wcar* (carmine/sunion :s1 :s2))) (println "intersection") (println (wcar* (carmine/sinter :s1 :s2))) (println "diff") (println (wcar* (carmine/sdiff :s1 :s2) (carmine/sdiff :s2 :s1))) (println "Done"))
Výsledek získaný po spuštění tohoto demonstračního příkladu. Výsledky množinových operací jsou opět zvýrazněny:
Working with two sets Fill in sets s1 and s2 [0 0 4 4 [c a d b] [f c e d]] Set operations union [c a e d b f] intersection [c d] diff [[a b] [f e]] Done
6. Mapy (asociativní pole)
Jedním z nejpoužívanějších datových typů v systému Redis jsou mapy neboli asociativní pole. Každá mapa může obsahovat 232-1 dvojic klíč-hodnota, přičemž klíčem jsou řetězce. Příkazy pro práci s asociativními poli začínají prefixem „H“. Základním příkazem je hset určený pro uložení dvojice klíč-hodnota do množiny, ovšem častěji se setkáme s příkazem hmset, který umožňuje uložit větší množství dvojic jedinou operací. Opakem dvojice hset/hmset jsou operace hget pro přečtení jednoho prvku nebo hgetall pro přečtení všech dvojic (formou tabulky, tj. tabulka má dvakrát více prvků, než asociativní pole). Tyto operace si snadno odzkoušíme přímo z konzole Redisu:
127.0.0.1:6379> hset apole x 1 (integer) 1 127.0.0.1:6379> hset apole y 2 (integer) 1 127.0.0.1:6379> hget apole x "1" 127.0.0.1:6379> hget apole z (nil)
Přepis existující hodnoty operací hset:
127.0.0.1:6379> hset apole x "nova hodnota" (integer) 0 127.0.0.1:6379> hget apole x "nova hodnota"
Použití příkazů hmset a hgetall:
127.0.0.1:6379> hmset user:1000 username antirez password P1pp0 age 34 OK 127.0.0.1:6379> hgetall user:1000 1) "username" 2) "antirez" 3) "password" 4) "P1pp0" 5) "age" 6) "34" 127.0.0.1:6379> hset user:1000 password 12345 (integer) 0 127.0.0.1:6379> hgetall user:1000 1) "username" 2) "antirez" 3) "password" 4) "12345" 5) "age" 6) "34"
7. Práce s mapami v jazyku Clojure
Příkazy, které byly otestovány v konzoli Redisu, si můžeme vyzkoušet i přímo v programovacím jazyce Clojure. Vzhledem k tomu, že hodnoty prvků jsou serializovány knihovnou Nippy (viz úvodní článek) je v dalším demonstračním příkladu ukázáno použití prvků různých typů, konkrétně seznamů, vektorů, ale i množin či map (přesněji řečeno množin a map v kontextu jazyka Clojure, který tyto datové typy plně podporuje):
(ns carmineB.core (:require [taoensso.carmine :as carmine :refer (wcar)] [clojure.pprint :as pprint])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Working with maps") (println "hset operation") (println (wcar* (carmine/hset :m1 :foo :bar) (carmine/hset :m1 :bar :baz) (carmine/hset :m1 "result" 1/3) (carmine/hset :m1 "more-complicated" [1 2 3]) (carmine/hset :m1 :boolean true) (carmine/hset :m1 :nil-value nil) (carmine/hset :m1 :text "Hello world!") (carmine/hset :m1 :list '(1 2 3)) (carmine/hset :m1 :vector [1 2 3]) (carmine/hset :m1 :a-set #{1 2 3 4}) (carmine/hset :m1 :map {:name "foo" :surname "bar" }))) (println "hget operation") (println (wcar* (carmine/hget :m1 :foo) (carmine/hget :m1 :bar) (carmine/hget :m1 :baz) (carmine/hget :m1 "result") (carmine/hget :m1 "more-complicated") (carmine/hget :m1 :unknown))) (println "hgetall operation") (pprint/pprint (wcar* (carmine/hgetall :m1))) (println "Done"))
Po spuštění tohoto příkladu se nejprve prvky do mapy uloží a následně zase přečtou a vypíšou na terminál:
Working with maps hset operation [1 1 1 1 1 1 1 1 1 1 1] hget operation [bar baz nil 1/3 [1 2 3] nil] hgetall operation ["foo" "bar" "bar" "baz" "result" 1/3 "more-complicated" [1 2 3] "boolean" true "nil-value" nil "text" "Hello world!" "list" (1 2 3) "vector" [1 2 3] "a-set" #{1 4 3 2} "map" {:name "foo", :surname "bar"}] Done
hset operation [1 1 1 1 1 1 1 1 1 1 1]
8. Množiny s ohodnocenými prvky (uspořádané množiny)
Posledním datovým typem Redisu, o kterém se v dnešním článku zmíníme, jsou množiny s ohodnocenými prvky. V tomto datovém typu (kontejneru) je každému prvku přiřazeno číslo, které je následně použito při porovnávání jednotlivých prvků (množina je tedy částečně uspořádaná), při zpětném čtení prvků apod. To se hodí například při implementaci prioritních front apod. Příkazy, které s tímto datovým typem pracují, začínají prefixem „z“. Nejprve vytvoříme novou množinu a přidáme do ní několik prvků. Zadané číslo odpovídá ohodnocení prvků:
127.0.0.1:6379> zadd set 100 x (integer) 1 127.0.0.1:6379> zadd set 150 y (integer) 1 127.0.0.1:6379> zadd set 50 z (integer) 1 127.0.0.1:6379> zadd set -5 w (integer) 1
Hodnota ve skutečnosti může být reálné číslo, nikoli pouze číslo celé:
127.0.0.1:6379> zadd set 0.5 a (integer) 1
Aktuální pořadí prvku (na základě jeho ohodnocení) přečteme příkazem zrank:
127.0.0.1:6379> zrank set x (integer) 3 127.0.0.1:6379> zrank set w (integer) 0 127.0.0.1:6379> zrank set foo (nil)
Dále můžeme získat počet prvků množiny příkazem zcard, popř. příkazem zcount zjistit počet takových prvků, jejichž skóre (ohodnocení) leží v nějakém zadaném intervalu:
127.0.0.1:6379> zcard set (integer) 4 127.0.0.1:6379> zcount set -1000 1000 (integer) 4 127.0.0.1:6379> zcount set 0 1000 (integer) 3
Ohodnocení je možné změnit příkazem zincrby, kterému se zadá relativní přírůstek (samozřejmě může být i záporný a opět se nemusí jednat o celé číslo):
127.0.0.1:6379> zrank set x (integer) 3 127.0.0.1:6379> zincrby set 1000 x "1100" 127.0.0.1:6379> zrank set x (integer) 4 127.0.0.1:6379> zincrby set -2000 x "-900" 127.0.0.1:6379> zrank set x (integer) 0
Nad uspořádanými množinami je možné provádět i některé další operace, například získat ty prvky, jejichž ohodnocení se nachází mezi specifikovanými mezními hodnotami:
127.0.0.1:6379> zrangebyscore set 1 200 1) "z" 2) "y" 127.0.0.1:6379> zrangebyscore set 1 300 1) "z" 2) "y" 3) "x"
Příkazem zremrangebyscore lze odstranit prvky, jejichž ohodnocení (skóre) se nachází mezi mezními hodnotami (opět užitečné při implementaci některých variant prioritních front):
127.0.0.1:6379> zremrangebyscore set 1 200 (integer) 2 127.0.0.1:6379> zrangebyscore set -1000 1000 1) "w" 2) "x"
Pokus o vymazání prvků se skóre, které v množině neleží:
127.0.0.1:6379> zremrangebyscore set 1 200 (empty list or set)
9. Uspořádané množiny a jazyk Clojure
I manipulace s uspořádanými množinami je podle očekávání podporovaná knihovnou Carmine a tím pádem dostupná pro aplikace naprogramované v Clojure. Základní operace jsou ukázány v dalším demonstračním příkladu. Funkce a makra definovaná v knihovně Carmine odpovídají přímo protokolu Redisu (ostatně jedná se o generovaná jména, takže je plná kompatibilita Carmine-Redis zaručena automaticky):
(ns carmineC.core (:require [taoensso.carmine :as carmine :refer (wcar)] [clojure.pprint :as pprint])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Working with sorted sets") (println "Fill in sorted set s1") (println (wcar* (carmine/zadd :s1 0.9 :a) (carmine/zadd :s1 0.8 :b) (carmine/zadd :s1 0.7 :c) (carmine/zadd :s1 0.6 :d))) (println "Retrieving items from sorted set s1") (println (wcar* (carmine/zcard :s1) (carmine/zrangebyscore :s1 0 100) (carmine/zrangebyscore :s1 0.65 0.85))) (println "Done"))
Po spuštění tohoto demonstračního příkladu získáme následující informace:
Working with sorted sets Fill in sorted set s1 [1 1 1 1] Retrieving items from sorted set s1 [4 [d c b a] [c b]] Done
Důležiý je především výpis prvků s ohonocením 0..100 a poté 0.65 až 0.85:
[d c b a] [c b]
10. Komunikační strategie publish-subscribe
Jedna z velmi užitečných technologií, kterou najdeme v Redisu, je technologie implementující paradigma publish-subscribe (nebo též publisher-subscriber). Jedná se o jednu z forem posílání zpráv mezi několika subsystémy, které tak mohou pracovat relativně samostatně, mohou být nakonfigurovány a administrovány nezávisle na sobě a případná změna architektury může být snadnější, než kdyby byly tyto subsystémy propojeny přímo (například přes nějaké binární API). V praxi se setkáme jak s paradigmatem pojmenovaným publish-subscribe, tak i s frontami zpráv (message queues), ovšem mezi oběma technologiemi existuje několik rozdílů a každá se proto používá k odlišným účelům.
Nejprve se budeme zabývat komunikační strategií publish-subscribe. Mezi vlastnosti této komunikační strategie patří:
- Existuje jeden či několik zdrojů zpráv.
- Příjemců může být taktéž více, zpráva je doručena všem příjemcům, kteří se k odběru přihlásili.
- Pořadí zpráv je zaručeno.
- Většinou není zaručeno zpracování a ani přijetí zprávy (pokud se například příjemce odpojí, zbytku „pipeline“ to nevadí).
Toto paradigma se může použít například při implementaci různých komunikačních systémů atd. Příkladem může být chat, kde záleží na pořadí doručení zpráv a příjemců je většinou větší množství. Popř. se tato strategie používá v IoT, kde je důležité poslat (a přijmout) aktuální data a nikoli sledovat minulé hodnoty.
V Redisu nalezneme následujících šest příkazů, kterými je implementována komunikační strategie publish-subscribe:
Příkaz | Stručný popis příkazu |
---|---|
SUBSCRIBE | přihlášení se k odebírání jednoho kanálu nebo většího množství kanálů |
UNSUBSCRIBE | opak předchozího, odhlášení se z odebírání specifikovaných kanálů (popř. ze všech kanálů) |
PSUBSCRIBE | odpovídá SUBSCRIBE, ovšem pro jméno kanálu lze použít žolíkové znaky |
PUNSUBSCRIBE | odpovídá UNSUBSCRIBE, ovšem pro jméno kanálu lze použít žolíkové znaky |
PUBLISH | publikování zprávy do zvoleného kanálu |
PUBSUB | získání podrobnějších informací o stavu kanálů, přihlášených odebíratelů zpráv atd. |
U příkazů psubscribe a punsubscribe je možné ve jménu kanálu používat takzvané žolíkové znaky, které s velkou pravděpodobností znáte například z BASHe při specifikaci souborů. Mezi tyto znaky patří především hvězdička (nahrazuje libovolně dlouhou sekvenci znaků), otazník (nahrazuje jeden libovolný znak) a zápis množiny znaků: [znaky]. Žolíkové znaky se odlišují od zápisu regulárních výrazů především v tom, že „*“ a „?“ před sebou neobsahují specifikaci, jakých znaků se náhrada týká (tj. nepíše se například „.*“ ale jen „*“). Více informací je uvedeno například na stránce https://en.wikipedia.org/wiki/Glob_(programming).
11. Program konzumující zprávy (subscriber)
Vytvoření samotného konzumenta zpráv v jazyce Clojure je ve skutečnosti poměrně triviální. Postačuje totiž použít makro with-new-pubsub-listener, v němž se uvede seznam kanálů (resp. jejich jmen) a funkce, která se má zavolat ve chvíli, kdy je do daného kanálu poslána zpráva. Například pro kanál pojmenovaný „events“ můžeme takovou (anonymní) funkci definovat následovně:
{"events" (fn f [event] (println "Received event" event))}
Konzument ovšem může přijímat zprávy z většího množství kanálů:
{"kanál1" (fn f [event] (println "Received event" event))} {"kanál2" (fn f [event] (println "Received event" event))} {"kanál3" (fn f [event] (println "Received event" event))}
Popř.:
{"kanál*" (fn f [event] (println "Received event" event))}
Podívejme se nyní na úplný zdrojový kód konzumenta zpráv:
(ns carmineD.core (:require [taoensso.carmine :as carmine :refer (wcar)] [clojure.pprint :as pprint])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Listener to given channel") (carmine/with-new-pubsub-listener (:spec redis-connection) {"events" (fn f [event] (println "Received event" event))} (carmine/subscribe "events")))
12. Program produkující zprávy (publisher)
Následující program po svém spuštění vytvoří sto zpráv, které budou poslány do kanálu „events“. V případě, že bude současně spuštěný i předchozí příklad, budou zprávy přijaty, v opačném případě zahozeny:
(ns carmineE.core (:require [taoensso.carmine :as carmine :refer (wcar)])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Publisher") (doseq [i (range 100)] (println i) (println (wcar* (carmine/publish "events" (* i 100))))))
13. Použití front pro komunikaci
Knihovna Carmine obsahuje podporu pro tvorbu aplikací, které spolu komunikují přes fronty zpráv. V dalších dvou kapitolách si ukážeme jak producenta, tak i konzumenta takto posílaných zpráv, ovšem nejprve si připomeňme typické vlastnosti front zpráv (které se v některých ohledech liší od komuniační strategie publish-subscribe):
- Existuje jeden či několik zdrojů zpráv.
- Příjemců může být taktéž více, ovšem zpráva je typicky získána jen jedním z nich (příjemci se tedy o zprávy dělí).
- Obecně není zaručeno pořadí doručení zpráv.
- Zpráva je zpracována jen jedenkrát, ovšem pokud ji příjemce nezpracuje, může být doručena dalšímu příjemci.
- Volitelná vlastnost související s předchozím bodem: po nezpracování se zpráva vrací zpět do fronty.
Fronty zpráv se používají velmi často například ve chvíli, kdy se zpracovávají různé transakce, u nichž není nutné, aby jejich výsledek uživatel viděl v reálném čase. Do fronty se pouze uloží všechny informace o tom, jaká transakce se má provést a později si tuto operaci z fronty vyzvedne nějaký „worker“.
Alternativně lze fronty zpráv obecně využít pro dělbu práce mezi větším množstvím „workerů“, kteří mohou být vhodným způsobem naškálovány, mohou se zapnout v době, kdy je volný strojový čas atd.
14. Implementace workera přijímacího úkoly přes frontu
Ukažme si nyní, jak snadné je vytvoření workera, který přijímá úkoly přes frontu, konkrétně přes frontu nazvanou „task-queue“. Povšimněte si, že při přijetí zprávy se zavolá takzvaný handler, což je v našem případě anonymní funkce. Důležité je, aby tato funkce potvrdila přijetí zprávy tím, že vrátí hodnotu {:status :success}:
(fn [{:keys [message attempt]}] (println "Received" message) {:status :success})
Samotná obsluha fronty je v balíčku taoensso.carmine.message-queue, což znamená odlišnou hlavičku programu:
(ns carmineF.core (:require [taoensso.carmine.message-queue :as car-mq]))
Podívejme se nyní na úplný zdrojový kód workera:
(ns carmineF.core (:require [taoensso.carmine.message-queue :as car-mq])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "Worker") (car-mq/worker {:spec redis-connection} "task-queue" {:handler (fn [{:keys [message attempt]}] (println "Received" message) {:status :success})}) ;(car-mq/stop my-worker) )
15. Klient vytvářející zprávy pro workery
Zprávy posílané do fronty „task-queue“ můžeme pochopitelně vytvářet přímo v řádkovém klientu Redisu (redis-cli), ovšem pochopitelně je možné pro tento účel opět použít aplikaci naprogramovanou v jazyku Clojure. Po spuštění následujícího skriptu se do fronty „task-queue“ vloží sto zpráv, které mohou být kdykoli později přečteny:
(ns carmineG.core (:require [taoensso.carmine :as carmine :refer (wcar)] [taoensso.carmine.message-queue :as car-mq])) (def redis-connection { :pool {} :spec { :uri "redis://localhost@127.0.0.1:6379"}}) (defmacro wcar* [& body] `(carmine/wcar redis-connection ~@body)) (defn -main [& args] (println "") (doseq [i (range 100)] (println i) (println (wcar* (car-mq/enqueue "task-queue" (* i 100))))))
16. Seznam popsaných maker a funkcí knihovny Carmine
Makro/funkce | Oblast/typ | Stručný popis |
---|---|---|
ping | komunikační protokol | dotaz, zda je Redis připraven |
pong | komunikační protokol | odpověď Redisu na příkaz ping |
info | komunikační protokol | dotaz na vlastnosti Redisu |
type | komunikační protokol | získání typu prvky |
set | řetězce | uložení řetězce nebo serializovaného objektu |
get | řetězce | načtení řetězce nebo serializovaného objektu |
incr | numerické hodnoty | změna uložené hodnoty o jedničku |
incrby | numerické hodnoty | změna uložené hodnoty |
decr | numerické hodnoty | změna uložené hodnoty o jedničku |
decrby | numerické hodnoty | změna uložené hodnoty |
incrbyfloat | numerické hodnoty | změna uložené hodnoty |
lpush | seznamy | přidání prvku na začátek seznamu |
rpush | seznamy | přidání prvku na konec seznamu |
lpop | seznamy | přečtení prvního prvku ze seznamu s jeho odstraněním |
rpop | seznamy | přečtení posledního prvku ze seznamu s jeho odstraněním |
lset | seznamy | změna hodnoty prvku na určeném indexu v seznamu |
lindex | seznamy | přečtení prvku se zadaným indexem |
linsert | seznamy | přidání prvku na určený index seznamu (s posunem dalších prvků) |
llen | seznamy | přečtení délky seznamu |
sadd | množiny | přidání prvku či prvků do množiny |
scard | množiny | získání počtu prvků množiny |
smembers | množiny | přečtení prvků z množiny |
sismember | množiny | test existence prvku |
srem | množiny | odstranění prvku z množiny |
sunion | množiny | množinové sjednocení bez uložení výsledků |
sinter | množiny | množinový průnik bez uložení výsledků |
sdiff | množiny | množinový rozdíl bez uložení výsledků |
sunionstore | množiny | množinové sjednocení s uložením výsledků |
sinterstore | množiny | množinový průnik s uložením výsledků |
sdiffstore | množiny | množinový rozdíl s uložením výsledků |
hset | mapy | vložení prvku do mapy |
hget | mapy | přečtení prvku z mapy |
hmset | mapy | vložení více prvků do mapy |
hgetall | mapy | přečtení všech prvků z mapy |
zadd | množiny s ohodnocenými prvky | přidání prvku |
zrank | množiny s ohodnocenými prvky | pořadí prvku |
zcard | množiny s ohodnocenými prvky | počet prvků v množině |
zcount | množiny s ohodnocenými prvky | počet prvků s ohodnocením x až y |
zincrby | množiny s ohodnocenými prvky | změna ohodnocení prvku |
zrangebyscore | množiny s ohodnocenými prvky | prvky s ohodnocením x až y |
zremrangebyscore | množiny s ohodnocenými prvky | odstranění prvků s ohodnocením x až y |
17. Repositář s demonstračními příklady
Všechny minule i dnes popsané demonstrační příklady byly uloženy do repositáře dostupného na adrese https://github.com/tisnik/clojure-examples/. V tabulce umístěné pod tímto odstavcem jsou uvedeny odkazy na tyto příklady (vždy se přitom jedná o plnohodnotný projekt vyžadující jak samotný jazyk Clojure, tak i Leiningen a pochopitelně i virtuální stroj Javy):
18. Předchozí články o systému Redis
Se systémem Redis jsme se již na stránkách Rootu setkali, a to dokonce několikrát. Buď jsme si popisovali přímo přístup k Redisu z různých programovacích jazyků (což je konkrétně případ všech dále zmíněných článků zaměřených na jazyky Python a Go) nebo byl Redis použit ve funkci databáze resp. perzistentního úložiště různými message brokery (Celery, RQ, apod.). Poslední dva články pak popisují problematiku proudů v systému Redis:
- Databáze Redis (nejenom) pro vývojáře používající Python
https://www.root.cz/clanky/databaze-redis-nejenom-pro-vyvojare-pouzivajici-python/ - Databáze Redis (nejenom) pro vývojáře používající Python (dokončení)
https://www.root.cz/clanky/databaze-redis-nejenom-pro-vyvojare-pouzivajici-python-dokonceni/ - Použití databáze Redis v aplikacích naprogramovaných v Go
https://www.root.cz/clanky/pouziti-databaze-redis-v-aplikacich-naprogramovanych-v-go/ - Použití databáze Redis v aplikacích naprogramovaných v Go (2)
https://www.root.cz/clanky/pouziti-databaze-redis-v-aplikacich-naprogramovanych-v-go-2/ - Použití nástroje RQ (Redis Queue) pro správu úloh zpracovávaných na pozadí
https://www.root.cz/clanky/pouziti-nastroje-rq-redis-queue-pro-spravu-uloh-zpracovavanych-na-pozadi/ - Proudy (streams) podporované systémem Redis
https://www.root.cz/clanky/proudy-streams-podporovane-systemem-redis/ - Proudy (streams) podporované systémem Redis (dokončení)
https://www.root.cz/clanky/proudy-streams-podporovane-systemem-redis-dokonceni/
19. Odkazy na předchozí části seriálu o programovacím jazyku Clojure
- Clojure 1: Úvod
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/ - Clojure 2: Symboly, kolekce atd.
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/ - Clojure 3: Funkcionální programování
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-3-cast-funkcionalni-programovani/ - Clojure 4: Kolekce, sekvence a lazy sekvence
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/ - Clojure 5: Sekvence, lazy sekvence a paralelní programy
http://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/ - Clojure 6: Podpora pro paralelní programování
http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/ - Clojure 7: Další funkce pro paralelní programování
http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/ - Clojure 8: Identity, stavy, neměnné hodnoty a reference
http://www.root.cz/clanky/programovaci-jazyk-clojure-8-identity-stavy-nemenne-hodnoty-a-referencni-typy/ - Clojure 9: Validátory, pozorovatelé a kooperace s Javou
http://www.root.cz/clanky/programovaci-jazyk-clojure-9-validatory-pozorovatele-a-kooperace-mezi-clojure-a-javou/ - Clojure 10: Kooperace mezi Clojure a Javou
http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/ - Clojure 11: Generátorová notace seznamu/list comprehension
http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/ - Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
http://www.root.cz/clanky/programovaci-jazyk-clojure-12-preklad-programu-z-clojure-do-bajtkodu-jvm/ - Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
http://www.root.cz/clanky/programovaci-jazyk-clojure-13-preklad-programu-z-clojure-do-bajtkodu-jvm-pokracovani/ - Clojure 14: Základy práce se systémem maker
http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/ - Clojure 15: Tvorba uživatelských maker
http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/ - Programovací jazyk Clojure – triky při práci s řetězci
http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/ - Programovací jazyk Clojure – triky při práci s kolekcemi
http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/ - Programovací jazyk Clojure – práce s mapami a množinami
http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/ - Programovací jazyk Clojure – základy zpracování XML
http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/ - Programovací jazyk Clojure – testování s využitím knihovny Expectations
http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/ - Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
http://www.root.cz/clanky/programovaci-jazyk-clojure-nektere-uzitecne-triky-pouzitelne-nejenom-v-testech/ - Enlive – výkonný šablonovací systém pro jazyk Clojure
http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/ - Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
http://www.root.cz/clanky/nastroj-leiningen-a-programovaci-jazyk-clojure-tvorba-vlastnich-knihoven-pro-verejny-repositar-clojars/ - Novinky v Clojure verze 1.8.0
http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/ - Asynchronní programování v Clojure s využitím knihovny core.async
http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async/ - Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-pokracovani/ - Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-dokonceni/ - Vytváříme IRC bota v programovacím jazyce Clojure
http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/ - Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/ - Multimetody v Clojure aneb polymorfismus bez použití OOP
https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/ - Práce s externími Java archivy v programovacím jazyku Clojure
https://www.root.cz/clanky/prace-s-externimi-java-archivy-v-programovacim-jazyku-clojure/ - Clojure 16: Složitější uživatelská makra
http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/ - Clojure 17: Využití standardních maker v praxi
http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/ - Clojure 18: Základní techniky optimalizace aplikací
http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/ - Clojure 19: Vývojová prostředí pro Clojure
http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/ - Clojure 20: Vývojová prostředí pro Clojure (Vim s REPL)
http://www.root.cz/clanky/programovaci-jazyk-clojure-20-vyvojova-prostredi-pro-clojure-integrace-vimu-s-repl/ - Clojure 21: ClojureScript aneb překlad Clojure do JS
http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/ - Leiningen: nástroj pro správu projektů napsaných v Clojure
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/ - Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-2/ - Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-3/ - Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-4/ - Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-5/ - Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-6/ - Programovací jazyk Clojure a databáze (1.část)
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/ - Pluginy pro Leiningen
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/ - Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/ - Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi-2/ - Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk/ - Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-2/ - Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/ - Seesaw: knihovna pro snadnou tvorbu GUI v azyce Clojure (2)
http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-2/ - Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-3/ - Programovací jazyk Clojure a práce s Gitem
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/ - Programovací jazyk Clojure a práce s Gitem (2)
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/ - Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-dokonceni/ - Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/ - Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
https://www.root.cz/clanky/programovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/ - Novinky v Clojure verze 1.9.0
https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/ - Validace dat s využitím knihovny spec v Clojure 1.9.0
https://www.root.cz/clanky/validace-dat-s-vyuzitim-knihovny-spec-v-clojure-1–9–0/ - Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure/ - Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure (2)
https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure-2/ - Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure
https://www.root.cz/clanky/incanter-prostredi-pro-statisticke-vypocty-s-grafickym-vystupem-zalozene-na-clojure/ - Incanter: operace s maticemi
https://www.root.cz/clanky/incanter-operace-s-maticemi/ - Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/ - Babashka: interpret Clojure určený pro rychlé spouštění utilit z příkazového řádku
https://www.root.cz/clanky/babashka-interpret-clojure-urceny-pro-rychle-spousteni-utilit-z-prikazoveho-radku/ - Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw/ - Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw (2. část)
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw-2-cast/ - Pokročilý streaming založený na projektu Apache Kafka, jazyku Clojure a knihovně Jackdaw (streamy a kolony)
https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-projektu-apache-kafka-jazyku-clojure-a-knihovne-jackdaw-streamy-a-kolony/ - Řídicí struktury využitelné v programovacím jazyku Clojure
https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure/ - Řídicí struktury využitelné v programovacím jazyku Clojure (dokončení)
https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure-dokonceni/ - Formát EDN: extensible data notation
https://www.root.cz/clanky/format-edn-extensible-data-notation/ - Formát EDN: extensible data notation (dokončení)
https://www.root.cz/clanky/format-edn-extensible-data-notation-dokonceni/ - Čtyři různé podoby datové struktury map v programovacím jazyku Clojure
https://www.root.cz/clanky/ctyri-ruzne-podoby-datove-struktury-map-v-programovacim-jazyku-clojure/ - Programová tvorba diagramů v jazyku Clojure s využitím knihovny Rhizome
https://www.root.cz/clanky/programova-tvorba-diagramu-v-jazyku-clojure-s-vyuzitim-knihovny-rhizome/ - Využití Redisu z jazyka Clojure pomocí knihovny Carmine
https://www.root.cz/clanky/vyuziti-redisu-z-jazyka-clojure-pomoci-knihovny-carmine/
20. Odkazy na Internetu
- Carmine: a pure-Clojure Redis client & message queue
https://github.com/ptaoussanis/carmine - Redis streams and Clojure
https://tirkarthi.github.io/programming/2018/08/17/redis-streams-clojure.html - Clojure Redis using Carmine
https://clojure.tgenedavis.com/clojure-redis-using-carmine/ - Clojure with a Touch of Redis
https://clojure.tgenedavis.com/2020–07–04/clojure-with-a-touch-of-redis/ - Clojure Redis: Get and Set
https://clojure.tgenedavis.com/2020–07–07/clojure-redis-get-and-set/ - Clojure Redis Pub/Sub with Carmine
https://clojure.tgenedavis.com/2020–10–17/clojure-redis-pub-sub-with-carmine/ - Redis and Clojure (založeno na odlišné knihovně)
https://devender.me/2010/06/13/redis-and-clojure/ - Disque, an in-memory, distributed job queue
https://github.com/antirez/disque - Scripting Redis with Lua
https://redislabs.com/ebook/part-3-next-steps/chapter-11-scripting-redis-with-lua/ - Redis Lua script for atomic operations and cache stampede
https://engineering.linecorp.com/en/blog/redis-lua-scripting-atomic-processing-cache/ - Příkaz pro spuštění skriptu v jazyce Lua: EVAL script numkeys key [key …] arg [arg …]
https://redis.io/commands/eval - Redis Lua scripts debugger
https://redis.io/topics/ldb - Repositář projektu s Redis klientem pro jazyk Go
https://github.com/go-redis/redis - Stránky programovacího jazyka Lua
https://www.lua.org/ - Programovací jazyk Lua
https://www.palmknihy.cz/ucebnice-odborna-literatura/programovaci-jazyk-lua-12651 - Programming in Lua
https://www.lua.org/pil/ - Redis Lua Scripts – Itamar Haber
https://www.youtube.com/watch?v=eReTl8NhHCs - Building Databases with Redis Tutorial: Lua Script | packtpub.com
https://www.youtube.com/watch?v=mMfGNsAr7Bg - Repositář projektu redis-luajit (fork)
https://github.com/coleifer/redis-luajit - Type-safe Redis client for Go
https://redis.uptrace.dev/ - Dokumentace k balíčku redis
https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc - godis – redis client implement by golang, inspired by jedis.
https://github.com/piaohao/godis - How to Use Redis Go Client go-redis/redis with GoLang
https://kb.objectrocket.com/redis/how-to-use-redis-go-client-go-redis-redis-with-golang-592 - Adventures in message queues
http://antirez.com/news/88 - redeo
https://github.com/bsm/redeo - First-in, first-out queues
https://redislabs.com/ebook/part-2-core-concepts/chapter-6-application-components-in-redis/6–4-task-queues/6–4–1-first-in-first-out-queues/ - Stránky projektu Redis
https://redis.io/ - Introduction to Redis
https://redis.io/topics/introduction - Try Redis
http://try.redis.io/ - Redis tutorial, April 2010 (starší, ale pěkně udělaný)
https://static.simonwillison.net/static/2010/redis-tutorial/ - Redis: key-value databáze v paměti i na disku
https://www.zdrojak.cz/clanky/redis-key-value-databaze-v-pameti-i-na-disku/ - Praktický úvod do Redis (1): vaše distribuovaná NoSQL cache
http://www.cloudsvet.cz/?p=253 - Praktický úvod do Redis (2): transakce
http://www.cloudsvet.cz/?p=256 - Praktický úvod do Redis (3): cluster
http://www.cloudsvet.cz/?p=258