What are Redis "out_" prefix keys? - redis

I am seeing multiple out_ prefix keys in my Redis ( version 3+ ) . Can any one help me understand these keys ? Are these internal , temporary keys ?
The application does not create these keys .
[02.66%] Biggest zset found so far 'out_GVwthhmz' with 765025 members
[09.91%] Biggest zset found so far 'out_JIwnd8Cu' with 798580 members
[69.70%] Biggest zset found so far 'out_UcP6p4YL' with 801308 members
Thanks

There are no internal/temporary keys that Redis creates - these are definitely something that was created by an application. Good luck hunting for it - possible routes to investigate:
Run grep out_* on your source code
Use MONITOR and CLIENT LIST to hone onto the offender

Related

Redis Lua script to delete a number of keys stored in a set

I am holding a list of keys in a set: SADD keys a b c.
From a Redis Lua script, I need to remove all keys stored in the keys set. This is what I have in mind:
local keys = redis.call("SMEMBERS", KEYS[1])
redis.call("DEL", unpack(keys))
My question is, is this okay? I know that all keys used in a Lua script should be passed via the KEYS table. Would my example pose any issues, when using multiple Redis instances? If so, how should I tackle this issue?

How to really deal with indexing in Redis and correctly implement indexes

I am moving some "live" data structures from MySQL to REDIS. Using StackExchange C# Redis Client, I'm writing (due to some very project-specific restrictions) my own microORM code to store and retrieve object class entities from a Redis Database.
I am pushing c# object as hash keys in Redis.
My general question is about indexing on fields other than the "primary key".
Ok, I've read all the theory of sets and sorted sets, and how to add and remove members from sets, and so on.
I've added some code to correctly create set keys which contain entities hash keys, so that I can lookup those objects by simple indexes or sorted indexes.
However I cannot find or figure out a good strategy for solving the following problems:
1. Index maintenance on expiration
I'd like to add expiration to some object (hash) keys, so that old entities get purged automatically by Redis. However I cannot find a reilable way to update/purge relevant indexes besides running periodically a background task that scans index set keys for expired members and removes them (notification is not good for me)
2. Index updating when some object fields change
In some cases I need to update only a small fraction of hash key values, not the whole entity. If the fields being updated are part of one or more index set keys, I cannot figure out the best way to properly update the set keys.
For example, let's say I need to store a "Session" entity whose primary key is its ID (simple numerical integer), and I need to add an index on the "Node" string field (Node being the reference to the server currently serving the session):
class Session {
[RedisKey]
public int ID { get; set; }
public string RemoteIP { get; set; }
[RedisSimpleIndex]
public string Node { get; set; }
}
RedisKey and RedisSimpleIndex are attributes I use to extract via reflection which fields are used as primary key and which are used for indexing.
Let's suppose I have an instance of Session like this:
{ ID = 2, RemoteIP = "1.2.3.4", Node = "Server10" }
My routines are creating the following keys in Redis:
Hash key: "obj:Session:2"
Hash values: "ID" = "1", "RemoteIP" = "1.2.3.4", "Node" = "Server10"
Set key "idx:Session:Node:Server10"
Set members: "obj:Session:2"
which is fine for looking up all sessions on Server10.
However, if the very same session needs to be moved to a different server (e.g. Server8)and I want to update only the Node field in the Hash set, how can I update indexes too?
The only way I found so far is to SCAN all index keys with pattern idx:Session:Node:* and remove from them any member obj:Session:2, then create/update the index key for the new node (idx:Session:Node:Server8).
Moreover the SCAN command is not available in IDatabase or ITransaction interfaces, and in a HA Clustered environment things get worse since I need to determine which Redis server is holding relevant keys to make this procedure work.
Is there a better way to build/represent simple indexes in Redis? Is my approach wrong?
I'd like to add expiration to some object (hash) keys, so that old entities get purged automatically by Redis. However I cannot find a reilable way to update/purge relevant indexes besides running periodically a background task that scans index set keys for expired members and removes them (notification is not good for me)
You cannot expire individual KV pairs within a hash. This is was discussed in #167. There don't appear plans to change this.
I think, you should be able to use keyspace notifications to subscribe to expire events. You would have to have some worker that subscribes for them and updates all relevant indices accordingly. However, you might get some inconsistent data. For example, your worker might crash and leave the stale indices behind. Also the indices wouldn't be updated instantaneously, so you'd end up with a bit of stale data regardless.
Probably not the best idea, but you could also hack in some custom indexing logic into expire.c. The code seems fairly straightforward. The C module API by contrast doesn't appear to provide any way to hook into the eviction logic.
Another option is to not rely on Redis when it comes to handling expiration logic. So... you would still have a background job, but it would actually issue corresponding DEL commands for expired KV-pairs. This would also allow you to keep the index 100% up to date via transactions.
In some cases I need to update only a small fraction of hash key values, not the whole entity. If the fields being updated are part of one or more index set keys, I cannot figure out the best way to properly update the set keys.
I'm not sure which Redis client you're using, but I found the following pattern to be quite useful in the past:
You have some form of "Updater" class for each hash. It has setters for all relevant fields that could be updated (setFirstName, setLastName etc.).
When you set a field, you mark that particular field as "dirty" (e.g. via a separate boolean).
When you call "save", you update indices for fields that were marked as dirty.
The only way I found so far is to SCAN all index keys with pattern idx:Session:Node:* and remove from them any member obj:Session:2, then create/update the index key for the new node (idx:Session:Node:Server8).
This is cumbersome, but seems like the way to go. Sadly I don't think there is a better solution for this. You might want to consider maintaining a separate set with keys of index KV-pairs that would have to be updated though, as that way you'd avoid going over a bunch of keys that aren't relevant.
You might also want to check out an article about how to maintain those indices. As you already alluded to, there are basically two options: real-time using MULTI transactions or using batch jobs. Once you get into the territory of using key expiration, you are more or less forced to use the batch approach.

Redis: Find keys matching a pattern

How I can find keys matching a pattern like this:
Eg:
I have some keys:
abc:parent1
abc:parent2
abc:parent1:child1
abc:parent2:child2
How can I find only
abc:parent1
abc:parent2
Keys is specifically noted as a command not to be run in production due to the way it works. What you need here is to create an index of your keys. Use a set for storing the key names of the pattern you want. When you add a new we key, add the name of it to the set. For example:
Set abc:parent1:child1 breakfast
Sadd abc:parent1:index abc:parent1
Then when you need the list:
Smembers abc:parent1:index
Will give you the list, without the penalties and problems associated with using the "evil" keys command. Additionally you would remove an entry with sremove on key deletion. You also get as a benefit the ability to know how many keys are in the index with a single call.
If you absolutely, positively, MUST avoid using an index use SCAN instead of keys. The only time you should even consider keys is if you are running a debug slave where the only process using it is your debugging process.
Command KEYS pattern
will help you for the same, if it is not a production environment. (Never use keys in production)
ex:
redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "two"
2) "one"
3) "four"
For your specific example, the below command will work:
redis 127.0.0.1:6379> keys *parent[0-9]
1) "abc:parent2"
2) "abc:parent1"
Here's the detailed description of the command.
Update: Though the suggestion above helps you get the desired output, the redis KEYS command is evil as the others mentioned. KEYS is blocking and can consume a lot of RAM while preparing the response.
Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.
Thanks The Real Bill and Itamar, I got a better understanding.

best way to store a set linked to a hash in Redis?

I need to store data about classrooms and students in Redis.
I have hashes for classroom info, e.g.:
classroom:0
where 0 is the class room id and it has field value pairs like:
classroomName -> xx, teacherId -> yy
In order to store students for these classroom, I have separate Set, e.g:
studentsForClassroom:0, and this set contains array of student IDs in that class.
Following this design, in order to get all information about a class, I have to first do a hgetall command for classroom:0 and then a smembers command for studentsForClassroom:0.
Is this the right way? Any better solution?
Is it possible that the students SET can somehow be nested in the classroom hash so that when I do a hgetall, the entire students array is populated right there in the classroom data?
You're doing it right. Redis doesn't have nested data structures.
Since your classroom hashes and students sets are not too big, using HGETALL and SMEMBERS is OK but remember that for larger volumes you'd probably want to use HSCAN and SSCAN instead.
You should not be worried about this. Redis is blazing fast and it's the usual way to use it: making a lot of simple requests. Moreover node-redis automatically pipelines commands.
If you really have perfomance issues, ensure you installed hiredis. Node_redis will use it.

Find key by value

The think I'm trying to implement is an id table. Basically it has the structure (user_id, lecturer_id) which user_id refers to the primary key in my User table and lecturer_id refers to the primary key of my Lecturer table.
I'm trying to implement this in redis but if I set the key as User's primary id, when I try to run a query like get all the records with lecturer id=5 since lecturer is not the key, but value I won't be able to reach it in O(1) time.
How can I form a structure like the id table I mentioned in above, or Redis does not support that?
One of the things you learn fast while working with redis is that you get to design your data structure around your accessing needs, specially when it comes to relations (it's not a relational database after all)
There is no way to search by "value" with a O(1) time complexity as you already noticed, but there are ways to approach what you describe using redis. Here's what I would recommend:
Store your user data by user id (in e.g. a hash) as you are already doing.
Have an additional set for each lecturer id containing all user ids that correspond to the lecturer id in question.
This might seem like duplicating the data of the relation, since your user data would have to store the lecture id, and your lecture data would store user ids, but that's the (tiny) price to pay if one is to build relations in a no-relational data store like redis. In practical terms this works well; memory is rarely a bottleneck for small-ish data-sets (think thousands of ids).
To get a better picture at how are people using redis to model applications with relations, I recommend reading Design and implementation of a simple Twitter clone and the source code of Lamernews, both of which are written by redis author Salvatore Sanfilippo.
As already answered, in vanilla Redis there is no way to store the data only once and have Redis query them for you.
You have to maintain secondary indexes yourself.
However with the modules in Redis, this is not necessary true. Modules like zeeSQL, or RediSearch allow to store data directly in Redis and retrieve them with a SQL query (for zeeSQL) or simil SQL for RediSearch.
In your case, a small example with zeeSQL.
> ZEESQL.CREATE_DB DB
OK
> ZEESQL.EXEC DB COMMAND "CREATE TABLE user(user_id INT, lecture_id INT);"
OK
> ZEESQL.EXEC DB COMMAND "SELECT * FROM user WHERE lecture_id = 3;"
... your result ...