Redis Protocol
December 4, 2023 ยท View on GitHub
The Redis compatible API will write-through to PostgreSQL on mutating
operations (e.g., DEL or HSET), and also publish notifications on
cache changes.
Read only operations such as EXISTS, HGETALL or HGET are handled directly by the in memory ETS cache. These commands ultimately resolve in a call to ets:lookup/2, with the resultant tuple converted into a (usually) string representation for Redis.
Mutating operations, such as DEL or HSET automatically write through to PostgreSQL (after checking the cache to determine whether an insert or update is the appropriate SQL statement to use). Streaming replication updates the in memory cache with the updated values from the database.
The real-time replication stream from PostgreSQL is also published to
subscribers with table level granularity. For example a subscription
to __key*__:pub.grades.* will result in any changes to the grades
table being published to that subscriber. Internally erlang message
passing is used with a process group per
table. Row level granularity is not currently
implemented, but is on the back log.
RESP (the Redis Protocol) is handled by pgec_resp_emulator, supporting the following commands.
server
info
Get (very basic) information about the server. Note that statistics are available via the Prometheus and Grafana interfaces.
$ redis-cli info
# Server
redis_version:0.2.0-1-g525aba8
command
Get an array of command details. Currently returns an empty array, to support command line tools that expect this command to be available.
$ redis-cli command
(empty array)
connection
ping
Ping the server.
$ redis-cli ping
pong
$ redis-cli ping "hello world"
"hello world"
hello
Handshake with the server.
generic
del
Delete a key.
exists
Determine if a key exists.
$ redis-cli exists pub.grades.234-56-7890
(integer) 1
hash
hexists
Determine if a hash field exists.
$ redis-cli hexists pub.grades.234-56-7890 test1
(integer) 1
$ redis-cli hexists pub.grades.234-56-7890 test6
(integer) 0
hget
Get the value of a hash field stored in memory.
$ redis-cli hget pub.grades.234-56-7890 test1
"44.0"
Returns nil when the key is not present, or the field is not present
in the hash.
$ redis-cli hget pub.grades.234-56-7890 test6
(nil)
hgetall
Get all fields and values in a hash for a key stored in memory.
$ redis-cli hgetall pub.grades.234-56-7890
1) "test4"
2) "90.0"
3) "test3"
4) "80.0"
5) "test2"
6) "90.0"
7) "test1"
8) "44.0"
9) "ssn"
10) "234-56-7890"
11) "last"
12) "Rubble"
13) "grade"
14) "C-"
15) "first"
16) "Betty"
17) "final"
18) "46.0"
hkeys
Get all the fields in a hash.
$ redis-cli hkeys pub.grades.234-56-7890
1) "test4"
2) "test3"
3) "test2"
4) "test1"
5) "ssn"
6) "last"
7) "grade"
8) "first"
9) "final"
An empty array is returned when the key is not present.
$ redis-cli hkeys pub.grades.234-56-7823
(empty array)
hlen
Get the number of fields in a hash.
$ redis-cli hlen pub.grades.234-56-7890
(integer) 9
Zero is returned when the key is not present.
$ redis-cli hlen pub.grades.234-56-8790
(integer) 0
hset
Set the string value of a hash field.
insert
A SQL statement is executed by pgec to insert the row into the underlying PostgreSQL table. The inserted row is then replicated updating the in memory cache.
redis-cli hset pub.grades.321-21-4321 last Zella first Xiggy test1 47 test2 68 test3 54 test4 73 final 23 grade D+
update
A SQL statement is executed by pgec to update the row in the underlying PostgreSQL table. The updated row is then replicated updating the in memory cache.
$ redis-cli hset pub.grades.234-56-7890 test1 45.0
(integer) 1
Zero is returned if the field is not a member of the hash.
pubsub
psubscribe
$ redis-cli psubscribe '__key*__:pub.grades.*'
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__key*__:pub.grades.*"
3) (integer) 1
In another shell update one of the grades:
redis-cli hset pub.grades.234-56-7890 test1 45.0
(integer) 1
Or via SQL:
docker compose exec \
--no-TTY \
db \
psql \
--command="update grades set grade='C' where ssn='234-56-7890'"
A message will be streamed to the subscriber detailing the affected key.
1) "message"
2) "__keyspace@0__:pub.grades.234-56-7890"
3) "set"