-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cache: switch to Rueidis client for Redis #5593
cache: switch to Rueidis client for Redis #5593
Conversation
5c6f283
to
dd2529f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot! One sentence to fix in docs, otherwise LGTM!
docs/components/store.md
Outdated
* `GOREDIS` (the default one) | ||
* `RUEIDIS` | ||
|
||
The main difference is that [Rueidis](https://github.com/rueian/rueidis) supports [client-side caching](https://redis.io/docs/manual/client-side-caching/) which is really important. If you have high cardinality metrics then it means that it is no longer necessary to go to remote-object storage to get information about potentially thousands or millions of metrics. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have high cardinality metrics then it means that it is no longer necessary to go to remote-object storage to get information about potentially thousands or millions of metrics.
I think this is wrong. The client caching is for Redis client NOT object storage. Also how it helps with cardinality in particular?
Client side caching to me sounds like extra in-mem cache that is checked first before accessing shared cache in REDIS, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I am also a little bit confused. What's the benefits of client side caching over server side caching. Less network calls?
What's the status on this? Will we proceed with single client as we discussed? |
I talked with @hanjm in private and they depend on RESP2 support in the Redis client so unfortunately we cannot easily from go-redis to Rueidis. So, I propose moving forward with this custom |
Hi @GiedriusS, just let you know that rueidis now also works in RESP2 with client-side cache disabled. |
Cool. |
@GiedriusS @hanjm does this mean we can go forward with the original suggestion, i.e. replace clients? |
I think so. I'll update this PR soon. |
Testing out the newest Rueidis client before updating this PR (: |
We are looking forward to this change, sounds like deadlock is over (: |
8c84c55
to
12699e4
Compare
Replaced go-redis with rueidis and simplified everything since rueidis now supports RESP2 as well. Most notably, this includes support for Redis Enterprise. Also, support for disabling client-side caching has been added so I've adjusted the code for that too. I've been testing this in prod for 3 months+ if not more so I think this should be good to go 💪 huge thank you goes to @rueian for all of the development and support, and a great library ❤️ |
12699e4
to
afeecad
Compare
Switch client to rueidis because it is faster and supports client-side caching. Tested it in production for a few months. Signed-off-by: Giedrius Statkevičius <giedrius.statkevicius@vinted.com>
afeecad
to
7ee0670
Compare
pkg/cacheutil/redis_client.go
Outdated
return errors.New("both client key and certificate must be provided") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// RedisClient is a wrap of redis.Client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is now outdated.
pkg/cacheutil/redis_client.go
Outdated
redisClient := redis.NewClient(opts) | ||
if reg != nil { | ||
reg = prometheus.WrapRegistererWith(prometheus.Labels{"name": name}, reg) | ||
var disableCaching = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not disableCaching := false
? I thought we used var
only to declare variables and use their type's zero-value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this is client-side caching, right? Could the variable be named clientSideCacheEnabled
then? It is more concise with what it really is and avoids the "negative thinking" (which causes double negation when disableCaching = false
.
if _, err := c.Set(ctx, key, value, ttl).Result(); err != nil { | ||
level.Warn(c.logger).Log("msg", "failed to set item into redis", "err", err, "key", key, | ||
"value_size", len(value)) | ||
if err := c.client.Do(ctx, c.client.B().Set().Key(key).Value(rueidis.BinaryString(value)).ExSeconds(int64(ttl.Seconds())).Build()).Error(); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why here we use Set
with ExSeconds
being added later instead of Setex
, like in the SetMulti
function? Would be cool to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, wouldn't it be wise to use DoCache
here to populate the client side cache too? I don't see DoCache
or DoMultiCache
being used anymore and from what I understand from Rueidis' README those are functions that will also populate client side cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed there is MGetCache
for getting through client side cache, but I fail to see where we write to the client side cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @douglascamata,
The population of client side cache is done by rueidis when you get successful responses from DoCache
and DoMultiCache
with supported commands, such as GET and MGET.
SET is not supported by DoCache
by design, because the client must be tracked by redis server via cacheable requests to receive related invalidation notifications later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rueian gotcha, thanks for the clarification!
I thought it would be useful for us to populate the client side cache whenever we SET something, but it if the cost is another GET and by consequence of the design, might not be a good idea.
Signed-off-by: Giedrius Statkevičius <giedrius.statkevicius@vinted.com>
Thanks for the review @douglascamata, I've updated the PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good. Looking forward to merge it!
Btw let's fix the changelog. |
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work! Worth taking it to 0.30 release as well.
* cacheutil: replace go-redis with rueidis client Switch client to rueidis because it is faster and supports client-side caching. Tested it in production for a few months. Signed-off-by: Giedrius Statkevičius <giedrius.statkevicius@vinted.com> * cacheutil: fix according to review Signed-off-by: Giedrius Statkevičius <giedrius.statkevicius@vinted.com> Signed-off-by: Giedrius Statkevičius <giedrius.statkevicius@vinted.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: Bartlomiej Plotka <bwplotka@gmail.com>
Add support for the Rueidis client. It has been instrumental for us in
avoiding an incident in production from too much network load on the
servers. Since we have lots of alerting/recording rules that use
historical data i.e. from Thanos Store, it means that without
client-side caching the same data is retrieved repeatedly.
Rueidis sends a PTTL command to Redis after retrieving data from Redis
to know what the TTL is.
I contemplated sending a design doc for this but the design doc ended up
very slim. It's either something like this or:
undertaking);
type
field to differentiate clients.I think it's ready to go except for two things:
limitation in the Rueidis library;
probably don't want to cache sensitive things like index data for longer
then we're supposed to.
I'll try to work on these things if this whole idea of having different
clients look good to you.
Signed-off-by: Giedrius Statkevičius giedrius.statkevicius@vinted.com