Hlavní navigace

Využití Redisu z jazyka Clojure pomocí knihovny Carmine

27. 1. 2022
Doba čtení: 29 minut

Sdílet

 Autor: Clojure
Seznámíme se s využitím systému Redis v aplikacích naprogramovaných v Clojure. Použijeme přitom knihovnu Carmine. Kombinace Clojure a Redis nám umožní jednoduše zpracovávat strukturovaná data.

Obsah

1. Využití Redisu z jazyka Clojure pomocí knihovny Carmine

2. Překlad a instalace Redisu verze 6.2 (6.2.6)

3. Spuštění Redisu a kontrola připojení z CLI klienta

4. Klient pro systém Redis naprogramovaný v jazyce Clojure

5. Připojení k Redisu, poslání zprávy PING a obdržení zprávy PONG

6. Pomocné makro wcar* vytvořené pro každé připojení k Redisu

7. Alternativní způsob definice připojení k Redisu

8. Podporované datové typy, s nimiž Redis pracuje

9. Práce s řetězci uloženými do databáze

10. Uložení řetězce a zpětné přečtení řetězce realizované v Clojure

11. Řetězce či čísla?

12. Manipulace s číselnými hodnotami iniciovaná z Clojure

13. Uložení strukturovaných dat do Redisu: síla kombinace Redis+Clojure

14. Seznamy

15. Manipulace se seznamy uloženými v Redisu z Clojure

16. Kam dál?

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

20. Odkazy na Internetu

1. Využití Redisu z jazyka Clojure pomocí knihovny Carmine

V dnešním článku, který je součástí seriálu o programovacím jazyku Clojure se seznámíme se způsobem využití systému Redis v aplikacích vyvinutých právě v Clojure. Jak již bylo zmíněno v perexu, použijeme pro tento účel knihovnu Carmine. O tom, proč je někdy vhodné zkombinovat možnosti nabízené jazykem Clojure se systémem Redis, jsme se již taktéž ve stručnosti zmínili – plně se zde využije schopnost zpracování složitě strukturovaných dat v Clojure s flexibilitou a rychlostí Redisu.

Poznámka: v dalších kapitolách sice budou použity samostatně spustitelné demonstrační příklady, ovšem při zkoumání možností nabízených knihovnou Carmine je mnohem lepší si přes lein repl spustit interaktivní smyčku REPL a příkazy zapisovat buď přímo zde nebo propojit REPL s programátorským textovým editorem popř. s integrovaným vývojovým prostředím.

2. Překlad a instalace Redisu verze 6.2 (6.2.6)

Redis může být na některých systémech již nainstalován. To, jaká verze serveru je aktuálně nainstalována, lze zjistit následujícím příkazem:

$ redis-server --version
Poznámka: alternativně je možné sledovat hlášení serveru při jeho spouštění.

Na mnoha systémech nalezneme stále verzi 4.x (kterou v dnešním článku nelze využít) nebo 5.0.x, což je ostatně i případ mnou používaného systému Fedora 32:

Redis server v=5.0.9 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=699c550ace009f13

V případě, že se v repositářích vaší distribuce z nějakého důvodu nenachází novější verze Redisu, lze ji přeložit a nainstalovat přímo ze zdrojových kódů. To ve skutečnosti není nic složitého, protože závislosti Redisu jsou pouze minimální: základní knihovna glibc a volitelně též knihovna jemalloc (její použití je však možné zakázat, což může mít vliv na rychlost práce s pamětí, popř. na požadavky na větší množství virtuální paměti).

Poznámka: pochopitelně je nutné mít k dispozici o ekosystém gcc popř. jiného překladače jazyka C.

Poslední stabilní verzí Redisu je verze 6.2.6, takže se ji pokusíme nainstalovat. Stažení zdrojových kódů Redisu 6.2.6:

$ wget https://download.redis.io/releases/redis-6.2.6.tar.gz
 
--2022-01-24 19:53:49--  https://download.redis.io/releases/redis-6.2.6.tar.gz
Resolving download.redis.io (download.redis.io)... 45.60.123.1
Connecting to download.redis.io (download.redis.io)|45.60.123.1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2476542 (2,4M) [application/octet-stream]
Saving to: ‘redis-6.2.6.tar.gz’
 
redis-6.2.6.tar.gz  100%[===================>]   2,36M  3,47MB/s    in 0,7s
 
2022-01-24 19:53:50 (3,47 MB/s) - ‘redis-6.2.6.tar.gz’ saved [2476542/2476542]

Rozbalení tarballu:

$ tar xvfz redis-6.2.6.tar.gz

Překlad a instalace (pro jednoduchost se nepoužívá knihovna jmalloc):

$ cd redis-6.0.10
 
$ make distclean; make MALLOC=libc; make
 
$ make install

Kontrola, jaká verze Redisu je nyní k dispozici:

$ redis-server --version
 
Redis server v=6.2.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=eaea6515c6f672a7

3. Spuštění Redisu a kontrola připojení z CLI klienta

V dalších kapitolách se předpokládá, že se klienti budou připojovat k běžícímu serveru Redisu, a to na standardním portu 6379. Chování serveru, volba úložiště dat, jeho dostupnost i mimo lokální síť atd. jsou pochopitelně plně konfigurovatelné. O několika důležitých konfiguračních volbách jsme se již zmínili v tomto textu (ovšem určeném ještě pro Redis 4.x). Samotný server se spouští příkazem redis-server:

$ redis-server

Po spuštění by se měla vypsat informace o verzi Redisu, použitém konfiguračním souboru (ve výpisu níže není konfigurační soubor specifikován) a především o portu, ke kterému je možné se připojit z klientů:

26769:C 24 Jan 2022 19:57:44.333 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
26769:C 24 Jan 2022 19:57:44.333 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=26769, just started
26769:C 24 Jan 2022 19:57:44.333 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf
26769:M 24 Jan 2022 19:57:44.334 # You requested maxclients of 10000 requiring at least 10032 max file descriptors.
26769:M 24 Jan 2022 19:57:44.334 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted.
26769:M 24 Jan 2022 19:57:44.334 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'.
26769:M 24 Jan 2022 19:57:44.334 * monotonic clock: POSIX clock_gettime
 
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 6.2.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 26769
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           https://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'
 
26769:M 24 Jan 2022 19:57:44.334 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
26769:M 24 Jan 2022 19:57:44.334 # Server initialized
26769:M 24 Jan 2022 19:57:44.334 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
26769:M 24 Jan 2022 19:57:44.334 * Loading RDB produced by version 6.2.6
26769:M 24 Jan 2022 19:57:44.334 * RDB age 57 seconds
26769:M 24 Jan 2022 19:57:44.334 * RDB memory usage when created 0.51 Mb
26769:M 24 Jan 2022 19:57:44.334 # Done loading RDB, keys loaded: 0, keys expired: 0.
26769:M 24 Jan 2022 19:57:44.334 * DB loaded from disk: 0.000 seconds
26769:M 24 Jan 2022 19:57:44.334 * Ready to accept connections

V případě, že je server spuštěn v samostatném terminálu, je ho možné ukončit buď klávesovou zkratkou Ctrl+C nebo (jak je to běžné) příkazem kill:

^C
26769:signal-handler (1611248833) Received SIGINT scheduling shutdown...
26769:M 24 Jan 2022 20:07:13.469 # User requested shutdown...
26769:M 24 Jan 2022 20:07:13.469 * Saving the final RDB snapshot before exiting.
26769:M 24 Jan 2022 20:07:13.471 * DB saved on disk
26769:M 24 Jan 2022 20:07:13.471 # Redis is now ready to exit, bye bye...

Nyní se k serveru zkusíme připojit ze standardního klienta:

$ redis-cli

Prakticky ihned by se měla objevit výzva:

127.0.0.1:6379>

Vyzkoušíme základní komunikaci příkazem PING. Server by měl odpovědět zprávou PONG:

127.0.0.1:6379> PING
 
PONG

Vypsat si můžeme i konfiguraci serveru, a to konkrétně příkazem INFO:

127.0.0.1:6379> INFO
 
# Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:eaea6515c6f672a7
redis_mode:standalone
arch_bits:64
multiplexing_api:epoll
atomicvar_api:c11-builtin
gcc_version:7.3.1
process_id:7714
process_supervised:no
 
...
...
...
 
127.0.0.1:6379>
Poznámka: pokud předchozí příkazy nepracují korektně, je nutné se ujistit, že server běží na zadaném portu, že není blokováno připojení atd.

4. Klient pro systém Redis naprogramovaný v jazyce Clojure

Nyní si ukažme, jakým způsobem je možné naprogramovat jednoduchého klienta pro systém Redis, a to s využitím programovacího jazyka Clojure a knihovny Carmine. Nejprve je nutné vytvořit nový projekt v Clojure. Pro tento účel využijeme systém Leiningen (i když novější verze Clojure se již mnohdy bez Leiningenu obejdou):

$ lein new app carmine1
 
Generating a project called carmine1 based on the 'app' template.

Výše uvedený příkaz vytvoří projekt v adresáři nazvaném „carmine1“, v němž se mj. nachází i projektový soubor „project.clj“:

$ cat project.clj
 
(defproject carmine1 "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.1"]]
  :main ^:skip-aot carmine1.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

Tento projektový soubor je zapotřebí upravit – přidat do něj závislost na knihovně Carmine. Viz zvýrazněný řádek:

(defproject carmine1 "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [com.taoensso/carmine "3.1.0"]]
  :main ^:skip-aot carmine1.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

Nyní můžeme přistoupit k dalšímu kroku, a to konkrétně ke stažení všech balíčků, na nichž tento projekt závisí. Kromě první knihovny (Carmine) se jedná o tranzitivní závislosti:

$ lein deps
 
Retrieving com/taoensso/carmine/3.1.0/carmine-3.1.0.pom from clojars
Retrieving com/taoensso/encore/3.9.2/encore-3.9.2.pom from clojars
Retrieving com/taoensso/truss/1.6.0/truss-1.6.0.pom from clojars
Retrieving com/taoensso/timbre/5.1.0/timbre-5.1.0.pom from clojars
Retrieving com/taoensso/encore/3.4.0/encore-3.4.0.pom from clojars
Retrieving io/aviso/pretty/0.1.37/pretty-0.1.37.pom from clojars
Retrieving com/taoensso/nippy/3.1.1/nippy-3.1.1.pom from clojars
Retrieving org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.pom from central
Retrieving org/iq80/snappy/snappy/0.4/snappy-0.4.pom from central
Retrieving org/tukaani/xz/1.8/xz-1.8.pom from central
Retrieving org/lz4/lz4-java/1.7.1/lz4-java-1.7.1.pom from central
Retrieving org/apache/commons/commons-pool2/2.9.0/commons-pool2-2.9.0.pom from central
Retrieving org/apache/commons/commons-parent/52/commons-parent-52.pom from central
Retrieving org/apache/apache/23/apache-23.pom from central
Retrieving commons-codec/commons-codec/1.15/commons-codec-1.15.pom from central
Retrieving org/iq80/snappy/snappy/0.4/snappy-0.4.jar from central
Retrieving org/tukaani/xz/1.8/xz-1.8.jar from central
Retrieving org/lz4/lz4-java/1.7.1/lz4-java-1.7.1.jar from central
Retrieving commons-codec/commons-codec/1.15/commons-codec-1.15.jar from central
Retrieving org/apache/commons/commons-pool2/2.9.0/commons-pool2-2.9.0.jar from central
Retrieving com/taoensso/encore/3.9.2/encore-3.9.2.jar from clojars
Retrieving com/taoensso/timbre/5.1.0/timbre-5.1.0.jar from clojars
Retrieving com/taoensso/nippy/3.1.1/nippy-3.1.1.jar from clojars
Retrieving com/taoensso/truss/1.6.0/truss-1.6.0.jar from clojars
Retrieving com/taoensso/carmine/3.1.0/carmine-3.1.0.jar from clojars
Poznámka: naprosto stejným způsobem byly připraveny i další projekty. Z nich si vždy ukážeme pouze obsah souboru „src/jméno_projektu/core.clj“, což je soubor, v němž se hledá a spouští (přesněji řečeno volá nebo vyhodnocuje) funkce nazvaná „main-“.

5. Připojení k Redisu, poslání zprávy PING a obdržení zprávy PONG

Ukažme si nyní, jak by mohl vypadat program napsaný v jazyku Clojure, který se po svém spuštění připojí k Redisu, pošle mu zprávu PING a zobrazí odpověď, což by měla být zpráva PONG (to jsme si ostatně ukázali ve druhé kapitole). Nejprve je nutné provést import knihovny Carmine:

(ns carmine1.core
  (:require [taoensso.carmine :as carmine)]))

V případě, že budeme chtít k některým symbolům (funkcím, makrům) přistupovat bez uvedení jména balíčku, můžeme tyto symboly korektně označit. Často budeme používat symbol wcar:

(ns carmine1.core
  (:require [taoensso.carmine :as carmine :refer (wcar)]))

Následně vytvoříme datovou strukturu (mapu) s informacemi o připojení k Redisu. Specifikovat je nutné především adresu a port, nepovinně též jméno a heslo, parametry SSL atd.:

(def redis-connection {
  :pool {}
  :spec {
    :host "127.0.0.1"
    :port 6379}})

A konečně můžeme začít komunikovat s Redisem. Použijeme přitom makro wcar (viz http://ptaoussanis.github­.io/carmine/taoensso.carmi­ne.html#var-wcar), kterému se předá jak informace o připojení, tak i příkaz, který se pošle na server. Zde se konkrétně jedná o příkaz PING. Makro wcar vrátí odpověď či odpovědi serveru, které vytiskneme:

(println (carmine/wcar redis-connection (carmine/ping)))
Poznámka: ve skutečnosti je volání Redisu provedeno asynchronně, takže interně vrácená hodnota není přímo odpovědí serveru, ale future objekt. To však při tisku nevadí.

Úplný zdrojový kód dnešního prvního demonstračního příkladu vypadá následovně:

(ns carmine1.core
  (:require [taoensso.carmine :as carmine :refer (wcar)]))
 
 
(def redis-connection {
  :pool {}
  :spec {
    :host "127.0.0.1"
    :port 6379}})
 
 
(defn -main
  [& args]
  (println "Pinging Redis")
  (println (carmine/wcar redis-connection (carmine/ping)))
  (println "Done"))

Spuštění příkladu (za předpokladu, že je Redis spuštěný):

$ lein run
 
Pinging Redis
PONG
Done

6. Pomocné makro wcar* vytvořené pro každé připojení k Redisu

Neustálé předávaní mapy redis-connection do makra carmine/wcar pouze zbytečně prodlužuje zdrojový kód. Můžeme si však vypomoci – buď vytvořením uzávěru nebo deklarací nového makra, které tento parametr do carmine/wcar předá automaticky, a to nezávisle na počtu dalších parametrů. Toto makro, které je převzato z oficiální dokumentace, může vypadat následovně:

(defmacro wcar*
  [& body]
  `(carmine/wcar redis-connection ~@body))
Poznámka: s makry jsme se již v článcích o programovacím jazyku Clojure setkali, takže jen krátce – v těle makra (to začíná zpětným apostrofem) se nahrazuje pouze parametr či parametry body.

Použití tohoto makra je jednoduché:

(println
  (wcar*
    (carmine/ping)))

Opět si ukažme úplný zdrojový kód dnešního druhého demonstračního příkladu:

(ns carmine2.core
  (:require [taoensso.carmine :as carmine :refer (wcar)]))
 
 
(def redis-connection {
  :pool {}
  :spec {
    :host "127.0.0.1"
    :port 6379}})
 
 
(defmacro wcar*
  [& body]
  `(carmine/wcar redis-connection ~@body))
 
 
(defn -main
  [& args]
  (println "Pinging Redis")
  (println
    (wcar*
      (carmine/ping)))
  (println "Done"))

Po spuštění tohoto příkladu by se měly zobrazit stejné informace, jako v případě příkladu předchozího:

$ lein run
 
Pinging Redis
PONG
Done

7. Alternativní způsob definice připojení k Redisu

Kromě specifikace adresy a portu, na kterém naslouchá Redis server, v samostatných atributech:

(def redis-connection {
  :pool {}
  :spec {
    :host "127.0.0.1"
    :port 6379}})

Je možné připojení určit i jediným řetězcem – URL:

(def redis-connection {
  :pool {}
  :spec {
    :uri "redis://localhost:6379"}})

Nebo se jménem:

(def redis-connection {
  :pool {}
  :spec {
    :uri "redis://localhost@127.0.0.1:6379"}})

Alternativně je možné v URL zadat i přihlašovací jméno a heslo:

(def redis-connection {
  :pool {}
  :spec {
    :uri "redis://jméno:heslo@127.0.0.1:6379"}})

Zbytek programu může zůstat stejný, jako tomu bylo v předchozích dvou demonstračních příkladech:

(ns carmine3.core
  (:require [taoensso.carmine :as carmine :refer (wcar)]))
 
 
(def redis-connection {
  :pool {}
  :spec {
    :uri "redis://localhost@127.0.0.1:6379"}})
 
 
(defmacro wcar*
  [&am; body]
  `(carmine/wcar redis-connection ~@body))
 
 
(defn -main
  [& args]
  (println "Pinging Redis")
  (println
    (wcar*
      (carmine/ping)))
  (println "Done"))

Zprávy zobrazené po spuštění:

$ lein run
 
Pinging Redis
PONG
Done

8. Podporované datové typy, s nimiž Redis pracuje

Při ukládání a zpracování dat ukládaných do Redisu je možné data reprezentovat několika datovými typy. Jména jednotlivých podporovaných typů jsou vypsána v tabulce pod tímto odstavcem a v navazujících kapitolách si řekneme o vybraných typech některé bližší informace (zaměřené spíše na jejich praktické použití, a to i s ohledem na jazyk Clojure):

Jméno Stručná charakteristika
string řetězce, které lze ovšem využít i pro práci s celými čísly i čísly s plovoucí řádovou čárkou
list seznamy, ve skutečnosti se s nimi pracuje jako se zásobníkem a frontou (podle zvolené sémantiky operací)
set množiny, je zaručena unikátnost prvků
sorted set množiny, v nichž jsou jednotlivé prvky ohodnoceny skórem
hash mapy (též asociativní pole)
bitmap (bit array) pole bitů, interně mapovány na řetězce
HyperLogLogs (HLL) datová struktura používaná pro zjištění počtu unikátních prvků (s určitou chybou, ovšem s malou spotřebou paměti)

9. Práce s řetězci uloženými do databáze

Základním datovým typem, který se v Redisu používá, jsou řetězce. Ve skutečnosti se jedná o sekvenci bajtů známé délky, které nejsou žádným způsobem interpretovány. Díky tomu, že je délka řetězce uložena ve zvláštním atributu, nemusí Redis používat například znak s kódem 0 pro ukončení řetězce a tudíž se i tento znak může bez problému v řetězci vyskytovat. Maximální délka řetězce je v současné verzi Redisu 512 MB, což v praxi znamená, že se řetězce mohou použít například pro uložení dokumentů, strukturovaných dat reprezentovaných ve formátech JSON, XML, YAML atd. atd.

Mezi základní příkazy pro práci s řetězci patří nám již známé příkazu set a get. Ovšem řetězce lze i modifikovat příkazem append a můžeme získat délku řetězce pomocí strlen:

127.0.0.1:6379> set z ""
OK
127.0.0.1:6379> append z "Hello"
(integer) 5
127.0.0.1:6379> append z " "
(integer) 6
127.0.0.1:6379> append z "world!"
(integer) 12
127.0.0.1:6379> get z
"Hello world!"
127.0.0.1:6379> strlen z
(integer) 12

Tyto základní operace je pochopitelně možné realizovat i z Clojure, což si ukážeme v následující kapitole.

10. Uložení řetězce a zpětné přečtení řetězce realizované v Clojure

Obdobou příkazu set ukázaného v předchozí kapitole je funkce carmine/set, které se v tom nejjednodušším případě předává pouze klíč a hodnota:

(carmine/set "klíč" "hodnota")))

Tato funkce se však musí volat v rámci makra wcar, které příkaz pošle do Redisu a vrátí výsledky. A my makro wcar máme obalené ve vlastním makru wcar*, takže:

(wcar*
  (carmine/set "klíč" "hodnota")))

Podobným způsobem je možné přečíst řetězec uložený pod známým klíčem:

(wcar*
  (carmine/get "klíč")))

Obě operace lze dokonce provést v rámci jedné sekvence příkazů poslaných Redisu:

(wcar*
  (carmine/set "klíč" "hodnota")))
  (carmine/get "klíč")))

V takovém případě se vrátí seznam výsledků pro jednotlivé vykonané příkazy.

Opět se podívejme na úplný tvar zdrojového kódu příkladu:

(ns carmine4.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 "Storing data")
  (println
    (wcar*
      (carmine/set "klíč" "hodnota")))
  (println "Done")
  (println "Retrieving data")
  (println
    (wcar*
      (carmine/get "klíč")))
  (println "Done"))

Pokusme se tento příklad spustit a získat výsledky:

$ lein run
 
Storing data
OK
Done
Retrieving data
hodnota
Done

11. Řetězce či čísla?

Zajímavé je, že i když Redis neobsahuje přímou podporu pro datový typ „celé číslo“, nabízí svým uživatelům několik operací určených pro atomickou změnu numerických hodnot reprezentovaných řetězcem v běžném dekadickém formátu. Pro zvýšení hodnoty o jedničku se používá operace INCR, opakem je pochopitelně funkce DECR. V případě, že budeme potřebovat zvýšit nebo snížit uloženou hodnotu o krok odlišný od jedničky, je možné pro tento účel použít operaci pojmenovanou příhodně INCRBY. Podívejme se na příklady (spouštěné přímo z redis-cli:

127.0.0.1:6379> set x 0
OK
127.0.0.1:6379> INCR x
(integer) 1
127.0.0.1:6379> get x
"1"
127.0.0.1:6379> INCRBY x 100
(integer) 101
127.0.0.1:6379> get x
"101"
127.0.0.1:6379> DECR x
(integer) 100
127.0.0.1:6379> get x
"100"
Proč vlastně tyto příkazy existují? Díky jejich existenci nemusíme zvýšení či snížení hodnoty řešit v transakci. Transakce lze samozřejmě použít, ale není nutné s nimi „plýtvat“ na takto jednoduchou věc.

Podobná operace nazvaná INCRBYFLOAT slouží pro změnu hodnoty čísla s desetinnou tečkou (opět ovšem uloženého formou běžného řetězce). Příklad na interpretaci řetězce jako čísla s plovoucí řádovou čárkou:

127.0.0.1:6379> set y 0.5
OK
127.0.0.1:6379> INCRBYFLOAT y 0.3
"0.8"
127.0.0.1:6379> get y
"0.8"

Řetězec „0.8“ ovšem již není možné považovat za reprezentaci celého čísla:

127.0.0.1:6379> incr y
(error) ERR value is not an integer or out of range
Poznámka: hodnoty uložené pod klíči „x“, „y“ a „z“ ve skutečnosti stále zůstávají řetězci:
127.0.0.1:6379> type x
string
127.0.0.1:6379> type y
string
127.0.0.1:6379> type z
string

12. Manipulace s číselnými hodnotami iniciovaná z Clojure

V knihovně Carmine nalezneme obdobu všech výše zmíněných příkazů:

Příkaz Redisu Funkce/makro v Carmine
INCR incr
INCRBY incrby
DECR decr
DECRBY decrby
INCRBYFLOAT incrbyfloat

Jejich použití je snadné, jak je to ostatně patrné i z vypsaného zdrojového kódu:

(ns carmine5.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 "Storing integer value")
  (println
    (wcar*
      (carmine/set "counter" 1)))
  (println "Done")
  (println "Retrieving integer value")
  (println
    (wcar*
      (carmine/get "counter")))
  (println "Done")
  (println "Increasing and retrieving new integer value")
  (println
    (wcar*
      (carmine/incr "counter")
      (carmine/get "counter")))
  (println "Done"))
Poznámka: poslední makro wcar* vrátí dvojici hodnot v seznamu. Konkrétně se jedná o seznam [2, 2], protože výsledkem příkazu incr je zvýšená hodnota (výsledek) a příkaz get vrací aktuální uloženou hodnotu. Ostatně si to můžeme velmi snadno vyzkoušet v praxi:
$ lein run
 
Storing integer value
OK
Done
Retrieving integer value
1
Done
Increasing and retrieving new integer value
[2 2]
Done

13. Uložení strukturovaných dat do Redisu: síla kombinace Redis+Clojure

Programovací jazyk Clojure je skvělý v těch oblastech, v nichž je nutné manipulovat se strukturovanými daty. A tato data je mnohdy zapotřebí ukládat do databáze. Jak však postupovat ve chvíli, kdy pracujeme (například) se složitější mapou, která navíc obsahuje hodnoty různých typů (popř. dokonce strukturované klíče)? Tato mapa může vypadat například takto:

{
 :boolean   true
 :nil-value nil
 :text      "Hello world!"
 :list      '(1 2 3)
 :vector    [1 2 3]
 :a-set     #{1 2 3 4}
 :map {:name    "foo"
       :surname "bar"
       }
}

Povšimněte si, že mapa jako své prvky obsahuje hodnoty různých datových typů Clojure, a to i typů, s nimiž Redis nedokáže přímo pracovat. Ve skutečnosti je mapa (či hodnota jakéhokoli jiného datového typu) interně serializována takovým způsobem, aby ji bylo možné uložit jako řetězec. Pro serializaci (a pochopitelně i zpětnou deserializaci) se používá knihovna nippy, s níž se na Rootu setkáváme poprvé. Ovšem z hlediska programátora používajícího knihovnu Carmine je vše provedeno automaticky – serializací a deserializací se vůbec nemusí zabývat. To je ostatně patrné i při pohledu na další demonstrační příklad, který vlastně provádí naprosto stejnou operaci jako příklad ukládající a čtoucí řetězec:

(ns carmine6.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))
 
 
(def data {
           :boolean   true
           :nil-value nil
           :text      "Hello world!"
           :list      '(1 2 3)
           :vector    [1 2 3]
           :a-set     #{1 2 3 4}
           :map {:name    "foo"
                 :surname "bar"
                 }})
 
(defn -main
  [& args]
  (println "Storing data structure")
  (println
    (wcar*
      (carmine/set "value" data)))
  (println "Done")
  (println "Retrieving data structure")
  (pprint/pprint
    (wcar*
      (carmine/get "value")))
  (println "Done"))

Příklad po svém spuštění skutečně mapu nejprve zapíše a poté ji přečte zpět:

$ lein run
 
Storing data structure
OK
Done
Retrieving data structure
{: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

Zajímavé bude zjistit, jak je vlastně tato datová struktura v Redisu uložena. Pro tento účel použijeme přímo redis-cli:

$ redis-cli
 
127.0.0.1:6379> get value
 
"\x00>NPY\x00p\aj\aboolean\bj\tnil-value\x03j\x04texti\x0cHello world!j\x04list\x19p\x02j\x04line*\x00\x00\x00\x15j\x06column*\x00\x00\x00\x18$\x03d\x01d\x02d\x03j\x06vectorrd\x01d\x02d\x03j\x05a-seto\x04d\x01d\x04d\x03d\x02j\x03mapp\x02j\x04namei\x03fooj\asurnamei\x03bar"

Takto vypadají binární data serializovaná výše zmíněnou knihovnou nippy.

14. Seznamy

Dalším datovým typem, který se v Redisu velmi často používá, jsou seznamy (list). Tento název je ovšem poněkud nepřesný, protože seznamy je možné využít například i pro implementaci fronty (queue), zásobníku (stack), běžného pole (array) nebo dokonce obousměrné fronty (deque). Počet prvků zapisovaných do seznamu může dosahovat prakticky neomezené hodnoty, konkrétně lze do jediného seznamu uložit 232-1 prvků. Mezi základní operace pro práci se seznamy patří:

Příkaz Význam
lpush přidání prvku na začátek seznamu
rpush přidání prvku na konec seznamu
lpop přečtení prvního prvku ze seznamu s jeho odstraněním
rpop přečtení posledního prvku ze seznamu s jeho odstraněním
   
lset změna hodnoty prvku na určeném indexu v seznamu
lindex přečtení prvku se zadaným indexem
   
linsert přidání prvku na určený index seznamu (s posunem dalších prvků)
llen přečtení délky seznamu

Podívejme se nyní na několik příkladů spouštěných z klienta redis-cli. Seznam uložený pod klíčem „l“ se automaticky vytvoří hned prvním příkazem:

127.0.0.1:6379> lpush l 3
(integer) 1
127.0.0.1:6379> lpush l 2
(integer) 2
127.0.0.1:6379> lpush l 1
(integer) 3
127.0.0.1:6379> llen l
(integer) 3
127.0.0.1:6379> rpush l 1
(integer) 4
127.0.0.1:6379> rpush l 2
(integer) 5
127.0.0.1:6379> rpush l 3
(integer) 6
127.0.0.1:6379> llen l
(integer) 6

Typ hodnoty uložené pod klíčem „l“:

127.0.0.1:6379> type l
list

Seznam nelze přečíst operací get:

127.0.0.1:6379> get l
(error) WRONGTYPE Operation against a key holding the wrong kind of value

Čtení prvků ze začátku i konce seznamu s jejich postupným odstraňováním:

127.0.0.1:6379> lpop l
"1"
127.0.0.1:6379> lpop l
"2"
127.0.0.1:6379> lpop l
"3"
127.0.0.1:6379> lpop l
"1"
127.0.0.1:6379> lpop l
"2"
127.0.0.1:6379> lpop l
"3"

Pokus o přečtení hodnoty z prázdného seznamu:

127.0.0.1:6379> lpop l
(nil)

15. Manipulace se seznamy uloženými v Redisu z Clojure

Výše uvedené operace lpush, lop, llen atd. je pochopitelně možné využít i v programovacím jazyku Clojure, protože tyto operace jsou podporovány knihovnou Carmine:

Příkaz Redisu Funkce/makro v Carmine
LPUSH lpush
RPUSH rpush
LPOP lpop
RPOP rpop
LSET lset
LINDEX lindex
LINSERT linsert
LLEN llen

Některé příkazy z předchozí tabulky budou otestovány v dnes již posledním demonstračním příkladu. Povšimněte si, že všechny příkazy jsou volány v rámci makra wcar* a tudíž budou do Redisu poslány v jediném bloku. Návratové hodnoty budou získány taktéž v jediném bloku, zpracovány a vráceny formou seznamu:

(ns carmine7.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 list")
  (println
    (wcar*
      (carmine/llen "a-list")
      (carmine/lpush "a-list" "first")
      (carmine/llen "a-list")
      (carmine/lpush "a-list" "second")
      (carmine/llen "a-list")
      (carmine/lpop "a-list")
      (carmine/llen "a-list")
      (carmine/lpop "a-list")
      (carmine/llen "a-list")
      (carmine/lpop "a-list")
      (carmine/llen "a-list")))
  (println "Done"))

Po spuštění tohoto příkladu dostaneme jako výsledek seznam s jedenácti hodnotami:

Working with list
[0 1 1 2 2 second 1 first 0 nil 0]
Done

Tyto hodnoty postupně odpovídají volaným příkazům, takže si je můžeme snadno rozkódovat:

Příkaz Hodnota vrácená tímto příkazem Poznámka
(carmine/llen „a-list“) 0 seznam je na začátku prázdný
(carmine/lpush „a-list“ „first“) 1 vložení prvního prvku, vrací se délka seznamu po vložení
(carmine/llen „a-list“) 1 počet prvků v seznamu je nyní roven jedné
(carmine/lpush „a-list“ „second“) 2 vložení druhého prvku, vrací se délka seznamu po vložení
(carmine/llen „a-list“) 2 počet prvků v seznamu je nyní roven dvěma
(carmine/lpop „a-list“) second přečtení hodnoty posledního prvku s jeho odstraněním ze seznamu
(carmine/llen „a-list“) 1 počet prvků v seznamu je nyní roven jedné
(carmine/lpop „a-list“) first přečtení hodnoty posledního prvku s jeho odstraněním ze seznamu
(carmine/llen „a-list“) 0 seznam je nyní prázdný
(carmine/lpop „a-list“) nil seznam je prázdný → nevrátila se žádná hodnota
(carmine/llen „a-list“) 0 seznam je stále prázdný
Poznámka: povšimněte si, že výchozí chování operace lpop je takové, že se nejedná o blokující operaci a současně se v případě prázdného seznamu vrátí hodnota nil, ale nevznikne výjimka.

16. Kam dál?

Redis se nepoužívá pouze ve funkci velmi rychlé databáze, ale velmi často se setkáme s tím, že je ústřední součástí message brokeru popř. je přímo použit pro realizaci fronty zpráv nebo pro streaming. A právě s tímto konceptem se seznámíme v navazující části tohoto článku.

Cloud 24 - tip 1

17. Repositář s demonstračními příklady

Všechny výše 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 Clojure, tak i Leiningen):

# Projekt Popis projektu Cesta
1 carmine1 připojení k Redisu, poslání zprávy PING a obdržení zprávy PONG https://github.com/tisnik/clojure-examples/tree/master/carmine1
2 carmine2 pomocné makro wcar* vytvořené pro každé připojení k Redisu https://github.com/tisnik/clojure-examples/tree/master/carmine2
3 carmine3 alternativní způsob definice připojení k Redisu https://github.com/tisnik/clojure-examples/tree/master/carmine3
4 carmine4 uložení řetězce a zpětné přečtení řetězce realizované v Clojure https://github.com/tisnik/clojure-examples/tree/master/carmine4
5 carmine5 využití příkazu incr https://github.com/tisnik/clojure-examples/tree/master/carmine5
6 carmine6 uložení strukturovaných dat do Redisu https://github.com/tisnik/clojure-examples/tree/master/carmine6
7 carmine7 manipulace se seznamy uloženými v Redisu https://github.com/tisnik/clojure-examples/tree/master/carmine7

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:

  1. Databáze Redis (nejenom) pro vývojáře používající Python
    https://www.root.cz/clanky/databaze-redis-nejenom-pro-vyvojare-pouzivajici-python/
  2. 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/
  3. 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/
  4. 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/
  5. 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/
  6. Proudy (streams) podporované systémem Redis
    https://www.root.cz/clanky/proudy-streams-podporovane-systemem-redis/
  7. 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

  1. Clojure 1: Úvod
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/
  2. Clojure 2: Symboly, kolekce atd.
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/
  3. 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/
  4. 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/
  5. 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/
  6. Clojure 6: Podpora pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/
  7. Clojure 7: Další funkce pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/
  8. 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/
  9. 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/
  10. Clojure 10: Kooperace mezi Clojure a Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/
  11. Clojure 11: Generátorová notace seznamu/list comprehension
    http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/
  12. 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/
  13. 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/
  14. Clojure 14: Základy práce se systémem maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/
  15. Clojure 15: Tvorba uživatelských maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/
  16. Programovací jazyk Clojure – triky při práci s řetězci
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/
  17. Programovací jazyk Clojure – triky při práci s kolekcemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/
  18. Programovací jazyk Clojure – práce s mapami a množinami
    http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/
  19. Programovací jazyk Clojure – základy zpracování XML
    http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/
  20. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  21. 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/
  22. Enlive – výkonný šablonovací systém pro jazyk Clojure
    http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
  23. 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/
  24. Novinky v Clojure verze 1.8.0
    http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/
  25. 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/
  26. 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/
  27. 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/
  28. Vytváříme IRC bota v programovacím jazyce Clojure
    http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/
  29. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  30. Multimetody v Clojure aneb polymorfismus bez použití OOP
    https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/
  31. 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/
  32. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  33. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  34. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  35. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  36. 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/
  37. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/
  38. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  39. 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/
  40. 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/
  41. 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/
  42. 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/
  43. 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/
  44. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  45. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  46. 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/
  47. 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/
  48. 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/
  49. 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/
  50. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  51. 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/
  52. 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/
  53. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/
  54. Programovací jazyk Clojure a práce s Gitem (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/
  55. 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/
  56. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  57. Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
    https://www.root.cz/clanky/pro­gramovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/
  58. Novinky v Clojure verze 1.9.0
    https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/
  59. 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/
  60. 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/
  61. 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/
  62. 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/
  63. Incanter: operace s maticemi
    https://www.root.cz/clanky/incanter-operace-s-maticemi/
  64. Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
    https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/
  65. 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/
  66. 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/
  67. 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/
  68. 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/
  69. Řídicí struktury využitelné v programovacím jazyku Clojure
    https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure/
  70. Řídicí struktury využitelné v programovacím jazyku Clojure (dokončení)
    https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure-dokonceni/
  71. Formát EDN: extensible data notation
    https://www.root.cz/clanky/format-edn-extensible-data-notation/
  72. Formát EDN: extensible data notation (dokončení)
    https://www.root.cz/clanky/format-edn-extensible-data-notation-dokonceni/
  73. Č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/
  74. 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/

20. Odkazy na Internetu

  1. Carmine: a pure-Clojure Redis client & message queue
    https://github.com/ptaoussa­nis/carmine
  2. Redis streams and Clojure
    https://tirkarthi.github.i­o/programming/2018/08/17/re­dis-streams-clojure.html
  3. Clojure Redis using Carmine
    https://clojure.tgenedavis.com/clojure-redis-using-carmine/
  4. Clojure with a Touch of Redis
    https://clojure.tgenedavis.com/2020–07–04/clojure-with-a-touch-of-redis/
  5. Clojure Redis: Get and Set
    https://clojure.tgenedavis.com/2020–07–07/clojure-redis-get-and-set/
  6. Clojure Redis Pub/Sub with Carmine
    https://clojure.tgenedavis.com/2020–10–17/clojure-redis-pub-sub-with-carmine/
  7. Redis and Clojure (založeno na odlišné knihovně)
    https://devender.me/2010/06/13/redis-and-clojure/
  8. Disque, an in-memory, distributed job queue
    https://github.com/antirez/disque
  9. Scripting Redis with Lua
    https://redislabs.com/ebook/part-3-next-steps/chapter-11-scripting-redis-with-lua/
  10. Redis Lua script for atomic operations and cache stampede
    https://engineering.linecor­p.com/en/blog/redis-lua-scripting-atomic-processing-cache/
  11. Příkaz pro spuštění skriptu v jazyce Lua: EVAL script numkeys key [key …] arg [arg …]
    https://redis.io/commands/eval
  12. Redis Lua scripts debugger
    https://redis.io/topics/ldb
  13. Repositář projektu s Redis klientem pro jazyk Go
    https://github.com/go-redis/redis
  14. Stránky programovacího jazyka Lua
    https://www.lua.org/
  15. Programovací jazyk Lua
    https://www.palmknihy.cz/ucebnice-odborna-literatura/programovaci-jazyk-lua-12651
  16. Programming in Lua
    https://www.lua.org/pil/
  17. Redis Lua Scripts – Itamar Haber
    https://www.youtube.com/wat­ch?v=eReTl8NhHCs
  18. Building Databases with Redis Tutorial: Lua Script | packtpub.com
    https://www.youtube.com/wat­ch?v=mMfGNsAr7Bg
  19. Repositář projektu redis-luajit (fork)
    https://github.com/coleifer/redis-luajit
  20. Type-safe Redis client for Go
    https://redis.uptrace.dev/
  21. Dokumentace k balíčku redis
    https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc
  22. godis – redis client implement by golang, inspired by jedis.
    https://github.com/piaohao/godis
  23. 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
  24. Adventures in message queues
    http://antirez.com/news/88
  25. redeo
    https://github.com/bsm/redeo
  26. 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/
  27. Stránky projektu Redis
    https://redis.io/
  28. Introduction to Redis
    https://redis.io/topics/introduction
  29. Try Redis
    http://try.redis.io/
  30. Redis tutorial, April 2010 (starší, ale pěkně udělaný)
    https://static.simonwilli­son.net/static/2010/redis-tutorial/
  31. 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/
  32. Praktický úvod do Redis (1): vaše distribuovaná NoSQL cache
    http://www.cloudsvet.cz/?p=253
  33. Praktický úvod do Redis (2): transakce
    http://www.cloudsvet.cz/?p=256
  34. Praktický úvod do Redis (3): cluster
    http://www.cloudsvet.cz/?p=258

Byl pro vás článek přínosný?