Chapter 4: Redis/Valkey Fundamentals — Commands, Pipelining, RESP
What Redis Is (In PCG Context)
Redis (or Valkey, the open-source fork PCG uses) is an in-memory key-value store. In PCG it stores:
- UE session state (TEIDs, UEIP addresses, L2TP keys)
- PFCP session blobs
- Retransmission cache
- CGNAT chunk maps
It's accessed over TCP using the RESP protocol.
Basic Commands
# SET: store a key-value pair
SET session:12345 "\x08\x01\x12\x05..." # binary blob
# GET: retrieve by key
GET session:12345
# DEL: delete a key
DEL session:12345
# MSET: set MULTIPLE keys in ONE command (atomic)
MSET teid:1001 val1 teid:1002 val2 ueip:5678 val3
# MGET: get multiple keys in one command
MGET teid:1001 teid:1002 ueip:5678
RESP Protocol (Redis Serialization Protocol)
Commands are sent as text-based arrays over TCP:
// "SET mykey myvalue" on the wire (RESP3):
*3\r\n // array of 3 elements
$3\r\n // bulk string, 3 bytes
SET\r\n // the command
$5\r\n // bulk string, 5 bytes
mykey\r\n // the key
$7\r\n // bulk string, 7 bytes
myvalue\r\n // the value
// Total: ~40 bytes for a simple SET
Pipelining (Non-Atomic Batching)
Send multiple commands without waiting for replies, then read all replies at once:
Without pipelining (1 RTT per command):
Client: SET k1 v1 ──────────────────► Redis
Client: ◄────────────────────── +OK Redis
Client: SET k2 v2 ──────────────────► Redis
Client: ◄────────────────────── +OK Redis
Client: SET k3 v3 ──────────────────► Redis
Client: ◄────────────────────── +OK Redis
Total: 3 round trips
With pipelining (1 RTT for all):
Client: SET k1 v1 ─┐
SET k2 v2 ─┼────────────────► Redis
SET k3 v3 ─┘
Client: ◄──────────────── +OK +OK +OK Redis
Total: 1 round trip (3x faster!)
💡 PCG Already Pipelines
In data-plane, upf_session_ctrl_do_store() fires multiple DB operations in parallel (pipelining). It doesn't wait for each reply individually — it counts pending ops and continues when all complete. The feature makes this MORE explicit with MSET.
MSET vs Pipelining vs MULTI/EXEC
| Method | Atomic? | Performance | Use Case |
|---|---|---|---|
| Individual SETs (pipelined) | No | Good (1 RTT) | Independent keys, current PCG approach |
| MSET | Yes (all-or-nothing) | Best (1 command, less parsing) | Multiple related keys, new approach |
| MULTI/EXEC | Yes (transaction) | Worst (extra overhead) | When you need atomicity + other commands |
Patrik's benchmarks showed MSET is significantly faster than MULTI/EXEC. This is why the feature uses MSET for batching.
Valkey Cluster (PCG Setup)
// PCG runs a 6-node Valkey cluster: 3 masters + 3 replicas
// Keys are distributed across masters using hash slots (0-16383)
// slot = CRC16(key) % 16384
// IMPORTANT: MSET only works if ALL keys hash to the SAME slot
// Solution: use hash tags to force keys to same slot:
MSET {session:123}:teid val1 {session:123}:ueip val2
// {session:123} is the hash tag — only this part is hashed
// Both keys go to same slot → MSET works in cluster mode
Key Takeaways
- Redis = in-memory KV store, accessed via RESP protocol over TCP
- MSET: set multiple keys in one command (atomic, fastest)
- Pipelining: send N commands, read N replies (1 RTT, non-atomic)
- PCG already pipelines — feature adds explicit MSET for even better performance
- In cluster mode, MSET requires all keys on same hash slot (use hash tags)
- MSET > pipelined SETs > MULTI/EXEC (performance order)