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/sjaOsHoF6KY
# New Video - https://youtu.be/gwtoJTevxSA

[<img src="assets/280.png?raw=true">](https://youtu.be/sjaOsHoF6KY)
[<img src="assets/281.png?raw=true">](https://youtu.be/gwtoJTevxSA)

# Consulting

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

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

```bash
# ec2: c8g.4xlarge -> 16/32
/usr/local/bin/redis-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no
/usr/local/bin/valkey-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no
```

## Redis

```bash
sudo apt -y install build-essential pkg-config

export REDIS_VER="8.6.0"

wget https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz
tar -xzf ${REDIS_VER}.tar.gz
sudo mv redis-${REDIS_VER}/ /opt/redis
cd /opt/redis/
make
sudo make install

cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF

sudo sysctl vm.overcommit_memory=1

sudo useradd --system --no-create-home --shell /bin/false redis

sudo tee /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis
Wants=network-online.target
After=network-online.target

StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
LimitNOFILE=100000
User=redis
Group=redis
Type=simple
Restart=on-failure
RestartSec=30s
ExecStart=/usr/local/bin/redis-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redis
```

## Valkey

```bash
sudo apt -y install build-essential pkg-config

export VALKEY_VER="9.0.2"

wget https://github.com/valkey-io/valkey/archive/refs/tags/${VALKEY_VER}.tar.gz
tar -xzf ${VALKEY_VER}.tar.gz
sudo mv valkey-${VALKEY_VER}/ /opt/valkey
cd /opt/valkey/
make
sudo make install

cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF

sudo sysctl vm.overcommit_memory=1

sudo useradd --system --no-create-home --shell /bin/false valkey

sudo tee /etc/systemd/system/valkey.service <<EOF
[Unit]
Description=Valkey
Wants=network-online.target
After=network-online.target

StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
LimitNOFILE=100000
User=valkey
Group=valkey
Type=simple
Restart=on-failure
RestartSec=30s
ExecStart=/usr/local/bin/valkey-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable valkey
sudo systemctl start valkey
sudo systemctl status valkey
```
16 changes: 16 additions & 0 deletions lessons/281/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM golang:1.26.0-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/281/app/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module app

go 1.26.0

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.17.3
)

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.67.5 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/sys v0.41.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
)
60 changes: 60 additions & 0 deletions lessons/281/app/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1DQx4=
github.com/redis/go-redis/v9 v9.17.3/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.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
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/281/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/281/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/281/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/281/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
Loading