|
| 1 | +--- |
| 2 | +title: A Very Brief Redis Introduction |
| 3 | + |
| 4 | +# Use letters for affiliations |
| 5 | +author: |
| 6 | + - name: Dirk Eddelbuettel |
| 7 | + affiliation: 1 |
| 8 | +address: |
| 9 | + - code: 1 |
| 10 | + address: Department of Statistics, University of Illinois, Urbana-Champaign, IL, USA |
| 11 | + |
| 12 | +# For footer text TODO(fold into template, allow free form two-authors) |
| 13 | +lead_author_surname: Eddelbuettel |
| 14 | + |
| 15 | +# Place DOI URL or CRAN Package URL here |
| 16 | +doi: "https://cran.r-project.org/package=RcppRedis" |
| 17 | + |
| 18 | +# Abstract |
| 19 | +abstract: | |
| 20 | + This note provides a very brief introduction to Redis highlighting its |
| 21 | + usefulness in multi-lingual statistical computing. |
| 22 | +
|
| 23 | +# Font size of the document, values of 9pt (default), 10pt, 11pt and 12pt |
| 24 | +fontsize: 9pt |
| 25 | + |
| 26 | +# Optional: Force one-column layout, default is two-column |
| 27 | +two_column: true |
| 28 | + |
| 29 | +# Optional: Enables lineno mode, but only if one_column mode is also true |
| 30 | +#lineno: true |
| 31 | + |
| 32 | +# Optional: Enable one-sided layout, default is two-sided |
| 33 | +#one_sided: true |
| 34 | + |
| 35 | +# Optional: Enable section numbering, default is unnumbered |
| 36 | +#numbersections: true |
| 37 | + |
| 38 | +# Optional: Specify the depth of section number, default is 5 |
| 39 | +#secnumdepth: 5 |
| 40 | + |
| 41 | +# Optional: Skip inserting final break between acknowledgements, default is false |
| 42 | +skip_final_break: true |
| 43 | + |
| 44 | +# Optional: Bibliography |
| 45 | +#bibliography: anytime |
| 46 | + |
| 47 | +# Optional: Enable a 'Draft' watermark on the document |
| 48 | +watermark: false |
| 49 | + |
| 50 | +# Customize footer, eg by referencing the vignette |
| 51 | +footer_contents: "RcppRedis Intro" |
| 52 | + |
| 53 | +# Produce a pinp document |
| 54 | +output: |
| 55 | + pinp::pinp: |
| 56 | + collapse: true |
| 57 | + keep_tex: false |
| 58 | + |
| 59 | +header-includes: > |
| 60 | + \newcommand{\proglang}[1]{\textsf{#1}} |
| 61 | + \newcommand{\pkg}[1]{\textbf{#1}} |
| 62 | +
|
| 63 | +# Required: Vignette metadata for inclusion in a package. |
| 64 | +vignette: > |
| 65 | + %\VignetteIndexEntry{Brief Redis Introduction} |
| 66 | + %\VignettePackage{RcppRedis} |
| 67 | + %\VignetteEngine{knitr::rmarkdown} |
| 68 | + %\VignetteEncoding{UTF-8} |
| 69 | + %\usepackage[utf8]{inputenc} |
| 70 | +--- |
| 71 | + |
| 72 | +```{r initialsetup, include=FALSE} |
| 73 | +knitr::opts_chunk$set(cache=TRUE) |
| 74 | +``` |
| 75 | + |
| 76 | + |
| 77 | +# Overview and Introduction |
| 78 | + |
| 79 | +[Redis][redis] is an very popular, very powerful, and very widely-used 'in-memory database-structure |
| 80 | +store'. It runs as a background process (a "daemon" in Unix lingo) and can be accessed locally or |
| 81 | +across a network making it very popular choice for 'data caches'. There is more to say about |
| 82 | +[Redis][redis] than we possibly could in a _short_ vignette introducing it, and other places already |
| 83 | +do so. The [Little Redis Book](https://www.openmymind.net/2012/1/23/The-Little-Redis-Book/), while a |
| 84 | +decade old (!!) is a fabulous _short_ start. The [official site][redis] is very good as well (but |
| 85 | +by now a little overwhelming as so many features got added). |
| 86 | + |
| 87 | +This vignette aims highlight two aspects: how easy it is to use [Redis][redis] on simple examples, |
| 88 | +and also to stress how [Redis][redis] enables easy _multi-lingual_ computing as it can act as a |
| 89 | +'middle-man' between any set of languages capable of speaking the [Redis][redis] protocol -- which |
| 90 | +may cover most if not all common languages one may want to use! |
| 91 | + |
| 92 | +# Examples One: Key-Value Setter and Getter |
| 93 | + |
| 94 | +We will show several simple examples for the |
| 95 | + |
| 96 | +- `redis-cli` command used directly or via shell scripts |
| 97 | +- \proglang{Python} via the standard \proglang{Python} package for [Redis][redis] |
| 98 | +- \proglang{C} / \proglang{C++} via the [hiredis][hiredis] library |
| 99 | +- \proglang{R} via \pkg{RcppRedis} utilising the [hiredis][hiredis] library |
| 100 | + |
| 101 | +to demonstrate how different languages all can write to and read from [Redis][redis]. Our first example will |
| 102 | +use the simplest possibly data structure, a simple `SET` and `GET` of a key-value pair. |
| 103 | + |
| 104 | +## Command-Line |
| 105 | + |
| 106 | +`redis-cli` is command-line client. Use is straightforward as shown an simply key-value getter and |
| 107 | +setter. We show use in 'shell script' form here, but the same commands also work interactively. |
| 108 | + |
| 109 | +```{bash cliGetSet} |
| 110 | +## note that document processing will show all |
| 111 | +## three results at once as opposed to one at time |
| 112 | +redis-cli SET ice-cream chocolate |
| 113 | +redis-cli GET ice-cream |
| 114 | +redis-cli GET ice-cream |
| 115 | +``` |
| 116 | + |
| 117 | +Here, as in general, we will omit hostname and authentication arguments: on the same machine, |
| 118 | +`redis-cli` and the background `redis` process should work 'as is'. For access across a (local or |
| 119 | +remote) network, the configuration will have to be altered to permit access at given network |
| 120 | +interfaces and IP address ranges. |
| 121 | + |
| 122 | +We show the [redis][redis] commands used in uppercase notation, this is in line with the |
| 123 | +documentation. Note, however, that [Redis][redis] itself is case-insensitive here so `set` is equivalent to |
| 124 | +`SET`. |
| 125 | + |
| 126 | +## Python |
| 127 | + |
| 128 | +[Redis][redis] does have bindings for most, if not all, languages to |
| 129 | +computing with data. Here is a simple \proglang{Python} example. |
| 130 | + |
| 131 | +```{python pyGetSet} |
| 132 | +import redis |
| 133 | +
|
| 134 | +redishost = "localhost" |
| 135 | +redisserver = redis.StrictRedis(redishost) |
| 136 | +
|
| 137 | +key = "ice-cream" |
| 138 | +val = "strawberry" |
| 139 | +res = redisserver.set(key, val) |
| 140 | +print("Set", val, "under", key, "with result", res) |
| 141 | +
|
| 142 | +key = "ice-cream" |
| 143 | +val = redisserver.get(key) |
| 144 | +print("Got", val, "from", key) |
| 145 | +``` |
| 146 | + |
| 147 | +For \proglang{Python}, the redis commands are generally mapped to (lower-case named) member functions of the |
| 148 | +instantiated redis connection object, here `redisserver`. |
| 149 | + |
| 150 | +## C / C++ |
| 151 | + |
| 152 | +Compiled languages work similarly. For \proglang{C} and \proglang{C++}, the [hiredis][hiredis] 'minimalistic' library from |
| 153 | +the [Redis][redis] project can be used---as it is by \pkg{RcppRedis}. Here we only show the code without executing |
| 154 | +it. This example is included in the package are as the preceding ones. \proglang{C} and \proglang{C++} work similarly to |
| 155 | +the interactive or \proglang{Python} commands. A simplified (and incomplete, see the `examples/` |
| 156 | +directory of the package for more) example of writing to [Redis][redis] would be |
| 157 | + |
| 158 | +```c++ |
| 159 | +redisContext *prc; // pointer to redis context |
| 160 | + |
| 161 | +std::string host = "127.0.0.1"; |
| 162 | +int port = 6379; |
| 163 | + |
| 164 | +prc = redisConnect(host.c_str(), port); |
| 165 | +// should check error here |
| 166 | +redisReply *reply = (redisReply*) |
| 167 | + redisCommand(prc, "SET ice-cream %s", value); |
| 168 | +// should check reply here |
| 169 | +``` |
| 170 | +
|
| 171 | +Reading is done by submitting for example a `GET` command for a key after which the `redisReply` |
| 172 | +contains the reply string. |
| 173 | +
|
| 174 | +## R |
| 175 | +
|
| 176 | +The \pkg{RcppRedis} packages uses the \pkg{Rcpp} Modules mechanism along with \pkg{Rcpp} to connect |
| 177 | +the [hiredis][hiredis] library to \proglang{R}. A simple \proglang{R} example inline with above |
| 178 | +follows |
| 179 | +
|
| 180 | +```{r RexSetGet} |
| 181 | +library(RcppRedis) |
| 182 | +redis <- new(Redis, "localhost") |
| 183 | +redis$set("ice-cream", "hazelnut") |
| 184 | +redis$get("ice-cream") |
| 185 | +``` |
| 186 | + |
| 187 | +# Example Two: Hashes |
| 188 | + |
| 189 | +[Redis][redis] has support for a number of standard data structures. One of these is hashes. |
| 190 | +The official documentation list [sixteen commands](https://redis.io/commands#hash) in the |
| 191 | +corresponding group covering writing (`hset`), reading (`hget`), checking for key (`hexists`), |
| 192 | +deleting a key (`hdel`) and more. |
| 193 | + |
| 194 | +```{bash cliHash} |
| 195 | +## note that document processing will show all |
| 196 | +## three results at once as opposed to one at time |
| 197 | +redis-cli HSET myhash abc 42 |
| 198 | +redis-cli HSET myhash def "some text" |
| 199 | +``` |
| 200 | + |
| 201 | +We can illustrate reading and checking from Python: |
| 202 | + |
| 203 | +```{python pyHash} |
| 204 | +print(redisserver.hget("myhash", "abc")) |
| 205 | +print(redisserver.hget("myhash", "def")) |
| 206 | +print(redisserver.hexists("myhash", "xyz")) |
| 207 | +``` |
| 208 | + |
| 209 | +For historical reasons, \pkg{RcppRedis} converts to/from \proglang{R} internal serialization on |
| 210 | +hash operations so it cannot _directly_ interoperate with these examples as they not deploy |
| 211 | +\proglang{R}-internal representation. The package has however a 'catch-all' command `exec` (which |
| 212 | +excutes a given \proglang{Redis} command string) which can be used here: |
| 213 | + |
| 214 | +```{r rHash} |
| 215 | +redis$exec("HGET myhash abc") |
| 216 | +redis$exec("HGET myhash def") |
| 217 | +redis$exec("HEXISTS myhash xyz") |
| 218 | +``` |
| 219 | + |
| 220 | +# Example Three: Lists |
| 221 | + |
| 222 | +So far we have looked at setters and getters for values, as well as for hashes. All of these |
| 223 | +covered only one value per key. But \proglang{Redis} has support for many more types. |
| 224 | + |
| 225 | +```{bash cliList} |
| 226 | +## note that document processing will show all |
| 227 | +## three results at once as opposed to one at time |
| 228 | +redis-cli LPUSH mylist chocolate |
| 229 | +redis-cli LPUSH mylist strawberry vanilla |
| 230 | +redis-cli LLEN mylist |
| 231 | +``` |
| 232 | + |
| 233 | + |
| 234 | +# Cleanup |
| 235 | + |
| 236 | +```{bash cleanup, include=TRUE} |
| 237 | +redis-cli hdel myhash abc |
| 238 | +redis-cli hdel myhash def |
| 239 | +redis-cli del ice-cream |
| 240 | +``` |
| 241 | + |
| 242 | +[redis]: https://redis.io |
| 243 | +[hiredis]: https://github.com/redis/hiredis |
0 commit comments