I'm implementing cache structure using Redis, my domain is like this:
- There are multiple categories (3000+ categories). Each category contains multiple questions (around 20-30 questions per category). Each question has several properties like whether it's published, what's the type, etc
- When loading the questions, I'll need to load questions from several categories and with some question filers specified by user that matches question properties: is published, type, etc
- I implement this in Redis using string and set:
- Each question is stored as string in Redis (serialized JSON) with key: "question:[QuestionId]"
- Each category has list of question ids belonging to it (Redis set) with key: "category:[CategoryId]:questions"
- For each category, each property filterable by user has its own set of question id (Redis set) e.g. published questions under category 1 has key: "category:1:questions:ispublished
- When loading the questions, I just need to based on the filters provided by user, do the intersect of set in Redis to find relevant question ids and load those questions
- So each category will have several cache items associated with it:
- category:[CategoryId]:questions
- category:[CategoryId]:questions:ispublished
- category:[CategoryId]:questions:notpublished
- category:[CategoryId]:questions:type:1
- category:[CategoryId]:questions:type:2 etc
This is working fine. But the challenging is to maintain consistency of cache items when there's eviction. Let's say if Redis cache decides to evict "category:[CategoryId]:questions:notpublished" cache item, how do i make sure all other cache items related to that category id also invalidated? I can do the checking of all the filters cache item to make sure they exist in cache before loading the questions, but that will require a lot of requests to Redis. Or any other strategy/way to solve my problem? I'm new to Redis and this is the first time I implement this type of cache structure in Redis
At the moment what I do is I just check for "category:[CategoryId]:questions" key. If it doesn't exist then I load data from database and set all cache items for that category. But it cannot detect if any other key is missing
1 Answer 1
You can attack this issue from a couple of angles:
- You can choose an eviction policy that will not evict those keys, e.g, eviction policy
volatile-lru
and set those keys without expiration. (more on eviction policies)
The issue here is that you might get OOM if there are no keys that can evict. - The second approach is to set an eviction listener, you can use the
notify-keyspace-events
to make redis publish keyspace and keyevent notifications. (more on key notifications)
The following command will make redis publish evictions on it keyspace notification channelredis-cli config set notify-keyspace-events Ke
And the following command will establish a connection subscribed to all redis notifications:redis-cli --csv psubscribe '__key*__:*'
This is clearly just an example of getting it done withredis-cli
, you should implement it as a separate thread in your application that deletes all evicted key related data from your dataset.
-
interesting. I didn't know about the keyspace events before. But I'm using Azure redis which seems not supporting keyspace events at the moment. So that leaves me with option 1 only. I guess I'll need to make sure the cache is not fullPhuong Nguyen– Phuong Nguyen11/17/2014 13:22:19Commented Nov 17, 2014 at 13:22
-
@PhuongNguyen, what did you end up doing? I'm in a similar situation and am considering implementing my own application level eviction strategy, whereby I manage the deletion of older dependent keys when newer ones get added.readyornot– readyornot06/25/2015 17:03:57Commented Jun 25, 2015 at 17:03
-
@readyornot I ended up with option 1, set keys with no expiration and make sure the cache has more than enough memory to store all data I need. I also have a worker to periodically check the cache and update from database to make sure the cache up-to-date with database. When I delete the parent key, I also make sure to delete all the dependency keysPhuong Nguyen– Phuong Nguyen06/26/2015 00:15:58Commented Jun 26, 2015 at 0:15