Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# New Video - https://youtu.be/UtyxjO8LJQs
# New Video - https://youtu.be/wWTjxLcMVsg

[<img src="assets/271.png?raw=true">](https://youtu.be/UtyxjO8LJQs)
[<img src="assets/272.png?raw=true">](https://youtu.be/wWTjxLcMVsg)

# Consulting

Expand Down
Binary file removed assets/271.png
Binary file not shown.
Binary file added assets/272.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions lessons/272/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Redis vs Valkey: Performance & Comparison

You can find tutorial [here](https://youtu.be/wWTjxLcMVsg).

```bash
# ec2: c8g.4xlarg
/usr/local/bin/redis-server --io-threads 9 --save --protected-mode no
/usr/local/bin/valkey-server --io-threads 9 --save --protected-mode no
```
16 changes: 16 additions & 0 deletions lessons/272/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM golang:1.25.4-trixie AS build

WORKDIR /app

COPY go.mod .
COPY go.sum .

RUN go mod download && go mod verify

COPY main.go .

RUN CGO_ENABLED=0 go build -o client main.go

FROM scratch

COPY --from=build /app/client /client
24 changes: 24 additions & 0 deletions lessons/272/app/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module app

go 1.25.4

require (
github.com/antonputra/go-utils v0.1.6
github.com/google/uuid v1.6.0
github.com/prometheus/client_golang v1.23.2
github.com/redis/go-redis/v9 v9.16.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/kr/text v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/sys v0.35.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
)
58 changes: 58 additions & 0 deletions lessons/272/app/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
github.com/antonputra/go-utils v0.1.6 h1:Dm2usCe6ydMVyG7jhimGSikEZ4H5Lg3+qZ/HcL33uRg=
github.com/antonputra/go-utils v0.1.6/go.mod h1:GtMYY62HViJnphNiXqce9btZRHMmrdUOfdZEgXJkb3M=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/redis/go-redis/v9 v9.16.0 h1:OotgqgLSRCmzfqChbQyG1PHC3tLNR89DG4jdOERSEP4=
github.com/redis/go-redis/v9 v9.16.0/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
133 changes: 133 additions & 0 deletions lessons/272/app/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"context"
"encoding/json"
"flag"
"fmt"
"time"

mon "github.com/antonputra/go-utils/monitoring"
"github.com/antonputra/go-utils/util"
"github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus"
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/v9/maintnotifications"
)

var ctx = context.Background()

// payload for the Redis
type User struct {
Handle string `json:"handle"`
Country string `json:"country"`
Timestamp int64 `json:"timestamp"`
Description string `json:"description"`
}

// String used to pad to ~512 bytes
const text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui kjdhf 13ye jasd sdhhu2edlka officia deserunt mollit anim id est laborum."

func main() {
// Define flags.
addr := flag.String("addr", "", "Redis address")
rate := flag.Int("rate", 10, "Number of requests per second")
pause := flag.Int("pause", 100, "Delays between requests in microseconds")

// Parse the flags.
flag.Parse()
fmt.Printf("Connecting to %s, rate: %d, pause: %d\n", *addr, *rate, *pause)

// Create Prometheus metrics.
reg := prometheus.NewRegistry()
m := mon.NewMetrics("client", []string{"version"}, []string{}, []string{"target"}, reg)
mon.StartPrometheus(8082, reg)

// Create Redis client.
rdb := redis.NewClient(&redis.Options{
Addr: *addr,
Password: "",
DB: 0,
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
},
})

// Set a 1-second TTL on the Redis keys.
expr := time.Duration(time.Duration(1) * time.Second)

// Initialize the start time and the counter to track the number of operations.
var start time.Time = time.Now()
var count int = 0

// Start an infinite loop and perform the work.
for {
// Keep track of the time elapsed between each operation.
end := time.Now()
elapsed := end.Sub(start)

// Reset the number of operations each second.
if elapsed >= time.Second {
start = time.Now()
count = 0
}

// If the number of operations equals or exceeds the rate, sleep for the remaining time until the next second.
// Sleeping avoids wasting CPU cycles, allowing for more efficient use of resources.
if count >= *rate {
next := time.Second - elapsed
if next > time.Nanosecond {
time.Sleep(next)
}
}

// Use a UUID as the key.
key := uuid.New()

// Create a User for the Test.
u := User{
Handle: "@antonvputra",
Country: "USA",
Timestamp: time.Now().UnixNano(),
Description: text,
}

// Serialize the user to a string.
value, err := json.Marshal(u)
if err != nil {
util.Warn(err, "rdb.Set failed")
continue
}

// Set the Redis key (UUID) to the timestamp value.
err = rdb.Set(ctx, key.String(), value, expr).Err()
if err != nil {
util.Warn(err, "rdb.Set failed")
continue
}

// Fetch the timestamp by the UUID key.
val, err := rdb.Get(ctx, key.String()).Result()
if err != nil {
util.Warn(err, "rdb.Get failed")
continue
}

// Load the user from Redis
var loaded User
json.Unmarshal([]byte(val), &loaded)

// Calculate the elapsed time between setting and retrieving the value in Redis.
delta := time.Now().UnixNano() - loaded.Timestamp
duration := time.Duration(delta)

// Record the operation duration using a Prometheus histogram.
m.Hist.WithLabelValues("redis").Observe(duration.Seconds())

// Increment the operation counter.
count++

// Pause execution to prevent overloading the target.
util.Sleep(*pause)
}
}
11 changes: 11 additions & 0 deletions lessons/272/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
services:
redis:
image: redis:8.2.3
ports:
- 6379:6379
networks:
- private

networks:
private:
7 changes: 7 additions & 0 deletions lessons/272/monitoring/0-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: benchmark
labels:
monitoring: prometheus
17 changes: 17 additions & 0 deletions lessons/272/monitoring/1-redis-mon.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: redis-client
namespace: benchmark
labels:
prometheus: main
spec:
namespaceSelector:
matchNames:
- benchmark
selector:
matchLabels:
app: redis-client
podMetricsEndpoints:
- port: metrics
17 changes: 17 additions & 0 deletions lessons/272/monitoring/2-valkey-mon.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: valkey-client
namespace: benchmark
labels:
prometheus: main
spec:
namespaceSelector:
matchNames:
- benchmark
selector:
matchLabels:
app: valkey-client
podMetricsEndpoints:
- port: metrics
38 changes: 38 additions & 0 deletions lessons/272/test/0-redis-client.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: redis-client
namespace: benchmark
spec:
parallelism: 650 # min 10, 25, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450
template:
metadata:
labels:
app: redis-client
spec:
restartPolicy: Never
terminationGracePeriodSeconds: 0
containers:
- name: redis-client
image: aputra/app-272:v4
command: [ "/client", "-addr", "redis.antonputra.pvt:6379", "-rate", "1000", "-pause", "5" ]
ports:
- name: metrics
containerPort: 8082
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 256Mi
cpu: 250m
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node
operator: In
values:
- clients
38 changes: 38 additions & 0 deletions lessons/272/test/1-valkey-client.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: valkey-client
namespace: benchmark
spec:
parallelism: 650 # min 10, 25, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450
template:
metadata:
labels:
app: valkey-client
spec:
restartPolicy: Never
terminationGracePeriodSeconds: 0
containers:
- name: valkey-client
image: aputra/app-272:v4
command: [ "/client", "-addr", "valkey.antonputra.pvt:6379", "-rate", "1000", "-pause", "5" ]
ports:
- name: metrics
containerPort: 8082
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 256Mi
cpu: 250m
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node
operator: In
values:
- clients
Loading