Збільшення швидкодії Redis-у через розділення на домени
Redis дуже простий і потужний інструмент, але хоч і має велику швидкодію та все ж однопотоковий.
Та якщо для кожного домену виділити окремий Redis то можна збільшити швидкодію, про це і буде дана стаття, про мікробенчмарки.
Передісторія
Майже в кожній компанії (6 із 7), де працював, використовувався Redis, а коли працював в LeBoutique то для кожного домену використовувався свій окремий Redis, перший для кешування HTML сторінок (@content), другий для збереження онлайну користувачів (@online), і третій для збереження лічильників переглядів продуктів (@views).
Порівняння швидкодії
Підготуємо три Redis-а та напишемо бенчмарки з використанням команди increment.
import ( "sync/atomic" "testing" "github.com/go-redis/redis" "github.com/stretchr/testify/require" ) var ( keys = []string{ "1", "2", "3", "4", "5", } keyCount = uint32(len(keys)) ) // https://github.com/go-redis/redis#quickstart func Client(addr string) (*redis.Client, error) { client := redis.NewClient(&redis.Options{ Addr: addr, // "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) err := client.Ping().Err() if err != nil { return nil, err } return client, err } func BenchmarkRedis1Increment(b *testing.B) { const ( addr1 = "redis1:6379" ) benchmarkIncrement(b, addr1, addr1, addr1) } func BenchmarkRedisAllIncrement(b *testing.B) { const ( addr1 = "redis1:6379" addr2 = "redis2:6379" addr3 = "redis3:6379" ) benchmarkIncrement(b, addr1, addr2, addr3) } func benchmarkIncrement(b *testing.B, addrs ...string) { b.Helper() var ( clientCount = uint32(len(addrs)) clients = make([]*redis.Client, clientCount) ) for i, addr := range addrs { var client, err = Client(addr) require.NoError(b, err) defer client.Close() var flushAllErr = client.FlushAll().Err() require.NoError(b, flushAllErr) clients[i] = client } var counter = uint32(0) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var index = atomic.AddUint32(&counter, 1) var client = clients[index%clientCount] var err = client.Incr(keys[index%keyCount]).Err() require.NoError(b, err) } }) }
В BenchmarkRedis1Increment використовується тільки 1 Redis, а в BenchmarkRedisAllIncrement вже 3 різні Redis-и.
Запустимо тести і порівнюємо швидкодію.
go test ./... -v -bench=. -benchmem -count=10 > bench.txt
benchstat bench.txt
name time/op Redis1Increment 8.36µs ± 2% RedisAllIncrement 5.54µs ± 2%
На такому простому прикладі швидкодія збільшилась на 33%.
Багатопотокова альтернатива KeyDB
KeyDB is a high performance fork of Redis with a focus on multithreading.
Заради цікавості дописав тести для KeyDB, ось повна картина:
name time/op Redis1Increment 9.30µs ± 1% RedisAllIncrement 6.68µs ± 8% Keydb1Increment 10.8µs ± 1% KeydbAllIncrement 8.05µs ± 1% Dragonflydb1Increment 12.3µs ± 3% DragonflydbAllIncrement 14.6µs ± 3%
Ще одна альтернатива Dragonfly
Dragonfly started as an experiment to see how an in-memory datastore could look like if it was designed in 2022Після новини на DOU додав тести для Dragonfly в репозиторій.
Висновки
Звісно на інших операціях з Redis збільшення швидкодії буде відрізнятись, але воно буде якщо розділяти на домени.
Мікробенчмарк доступний в репозиторії, можете використовувати як заготовку для ваших досліджень.
4 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів