Client side caching in Redis 6
antirez.com
antirez.com
Could there be some potential privacy or data-leakage concerns with this, since the server is now storing and acting on info about what data has been accessed, by which clients, and even when (to a limited degree)?
For example, say that some kind of sensitive data is stored in redis (e.g. user private messages). By watching for relevant invalidation messages (or if there's any way for clients to read the data in the Invalidation Table directly), it could be possible to learn some info about how that data was accessed.
Without knowing more about the implementation, I don't know if this is even a concern at all, and I haven't come up with a specific method of abusing it even if it is. I think it's probably something to keep in mind though.
If someone already has full access to the redis server, then yeah, I can't imagine how this would expose anything more than what's already available.
In your specific example, your client is also probably the one issuing the commands to store and retrieve the private messages in Redis - meaning, it already has access to all the data required for a breach. If you have an unrelated workload that is accessing a shared redis, but it does not need access to the sensitive data, perhaps, use an ACL to limit clients from the alternate workload to a different redis DB (which provides some level of isolation), or simply use a different redis entirely, and don't allow clients running the alternate workload to connect to the database that contains sensitive data.
1. The database anyway sees such connections and there is a continue stream of activity about clients, so there is also an instantaneous state that discloses who does what, at any time.
2. Companies trace everything in order to have data to do debugging when there are problems, so this information is stored at a much better level of details in other places as well.
3. There is no obvious way this could be exploited.
4. In general it is supposed that the clients can trust the server.
5. If you already violated Redis in order to read such info (not accessible via APIs), you can collect a lot more.
So based on initial thoughts I don't think this is going to be ever a security problem.
The gist is using pubsub to send invalidation messages consisting of item ID and time stamp, but also store the latest invalidation message into a set that is polled on every longer time period (10 seconds in my case). Listening to pubsub and polling are done per server that hosts the in memory cache for all items in the cache.
One interesting complication was how to make sure I don’t end up with the wrong (stale) cached item due to race condition between the read and the message passing. Imagine 2 thread, thread A reading and populating the cache, thread B listening to invalidation events. If thread A get held up (context switching, slow network, etc) it can actually populate into the cache after thread B has received and processed the invalidation message. To avoid that I ended up holding the invalidation messages and their receive time in the receiving server for a short duration (20 seconds - twice poll time). I required and in memory cache population to tell me the time from before the read command was sent to the cache. At the time of cache population, if I saw in had any invalidation message marked after the time the read command started I discarded that item instead of caching it. In highly concurrent, highly distributed application this turned to be a must-have.
Also, mainly to placate my fears, I had “panic mode”. If I didn’t see any message (I sent periodic maintenance messages) or if I couldn’t execute multiple polling attempts I dumped the whole cache and wouldn’t let any new item be ca he’d until communication was restored.
Implement it quick so I can use it on AWS in a few years!
It's definitely at least network-based, b/c you have to spin up instances of it in your VPC.
However, they also require custom clients, which is a little odd afaiu (b/c in theory DAX is API-compatible with DynamoDB, so why would regular dynamodb sdk clients not work?) so maybe the custom clients also add some in-process-based caching?
Disclaimer: happy user of a redis cluster :)
It makes super fast to work with data (it is already in process memory), and the centralized server handles consistency and transaction serialization.
It also wouldn't work very well as a proxy because then if any clients don't go through the proxy but change some of the data, there's no way for all the proxy-using clients to know.
It also looks like client / protocol implementations are about to get a lot more complex, even if the feature is being used by the majority of users?
On the second point, the post talks about having the feature disabled by default; I was curious regarding the protocol itself - it is currently quite simple, and by adding extra cache-control metadata it sounds like correct client implementation might become a lot more complex, but it’s hard to tell without having seen what the new protocol looks like.
About your second point: today I implemented even the feature (in the unstable branch) to support RESP2, that is, the current Redis protocol. But even using RESP3 the complexity is very low. On the data connection side you have just to use the CLIENT command to activate it. In the data connection, what you could receive, if you associate a callback in your client, is push data that notifies you the invalidation connection is no longer active. Push data is normally discarded by the client implementation of RESP3 if no handler is associated. On the invalidation connection, in RESP3 mode, you get again push data with a callback, or if you are in RESP2 mode, you just subscribe to the special channel __redis__:invalidate, and you get the messages about the caching slots that need to be invalidated.
I think you mean slot 5 in this sentence.
In "fast" languages (C# Java Go Rust Cxx) allocation tends to be fairly efficient so you're not wasting tons of space keeping objects in RAM.
These fast languages can max out the network interface most of the time using the right frameworks. In them, memory storage is also over 100x faster than remote like Redis.
Now if you've got something in PHP or Rails that can only manage 100 requests/second remote caches make tons of sense. The network overhead is nothing compared to how slow the language is. This advantage erodes when you're closer to native speed and local memory access is 1000 times faster than retrieving cached data over network.
TLDR: Redis and alike make sense when your language or framework is slow and the bottleneck is CPU use. They don't give you much when networking and memory bandwidth are your bottleneck because the language runs near native speed.
It might take you 3, 40, or a 100 tries for the same request till you hit a node that has your data cached. It could work with extremely high req/seconds, though in an unpredictable way.
Or I could use an off the shelf product that is probably better than whatever I could come up with, given, even, unrealistic amounts of time to perfect it. I could come up with something more suited to our use case only, but the moment the use case changes, I'd wonder why I didn't just go with Redis.
I haven't actually looked into a DIY method though. I just know I want something like Redis for our user table, because it's hit a lot, and the traffic tends to be repetitive.
Relevant to what? You've already got a microservice mesh, which means you've also got a microservice architecture that's supposed to handle all of the RPCs.
Adding a layer of Redis on top is probably going to introduce more entities into the system and make it less homogenous.
As you can probably tell, I'm not at all a fan of the way Redis is moving. It hit a sweet spot as a "better memcached" but apparently aspires to be a real database, so now this nice simple tool is all crazy. The new protocol just kinda sucks for synchronous use.
I'd go with a hand-written in-memory caching scheme before I ever considered a Redis sandwich with this feature. Seems like a complexity nightmare and very difficult to reason about. Yeah maybe I'm being crusty, but I'm just thinking about maintaining and debugging something like this and having cold sweats. The linked redisconf talk clearly bears this out. Sounds like they had a hell of a time. But then that also provides some measure of job security?