My Confusion regarding Redis
If I install Redis on my server and my 4 different clients connect to that same redis server, so how will the data between them will be kept separate so as one client does not override the key-value pair that other client has saved.
Eg:-
client-1 set name="adam"
client-2 set name="henry"
So as Redis server is common between these clients the name key set by client-1 will be overwritten by client-2, So when
client-1 execute get name ==> henry (As it has been updated which is wrong, he was expecting it to be adam)
So how does Redis separates the multiple user instance running on same server ? Does it create separate databases internally or stores as per user or what ?
Redis itself doesn't separate your data. You'd have to separate those by yourself. There are many options to do that.
Using Redis database: Redis supports multiple databases. Each application (in your case, client) can be set/allocated to use to use one specific database. This allocation has to be done in application end, not in Redis.
The limitations of this approach are: i) Redis supports at most 16 databases (denoted from 0 to 15). ii) Redis cluster mode supports only one database.
Note: SELECT command is used to select a specific database.
Namespacing: Each application can be (for example) assigned an unique prefix. They'd prefix all their keys with that assigned prefix.
Use separate Redis instance per application.
Since you have key-value pairs and you use the very same key for multiple clients, you will need to differentiate your clients. A way to do so would be to prepend the identifier of your client to each key. So, instead of set name you could do something like set client1_name. You would do well to implement some functions in your application that would be called like setName and getName and it would prepend the client identifier to the name under the hood. So, you implement your helper functions once, ensuring that it correctly builds the keys both for getters and setters and never again worry about the client.
Related
How can a single instance of Redis be used in a multi-tenant environment. Meaning multiple and different applications using the same Redis instance.
Suppose I have two apps, one is Baking App and the other one is Delivery App. Both apps will be using the same Redis instance and both apps will be saving similar keys with similar key patterns (e.g. userid:uuid -> johnsmith) etc. Obviously, using the same Redis will have collisions, is there a way to "Namespace" the database as such even the same key will be isolated from each other allowing multiple apps to use the same Redis instance concurrently?
And also work with Redis search, and in the same way, search and indexing would be isolated from each app. So if the search is on the Delivery App namespace it would not fetch anything from the Baking App namespace.
How can this be achieved?
So there are multiple things that you can do:
You can prefix the keys with app name like app1:userid:uuid etc
You can use different in memory db provided by redis. Redis supports upto 16 DBs. You can store keys for different apps in different db. To fetch them connect with respective DB.
You can use both of the above methods.
To improve security so that the Apps cannot access other App's data:
Implement Redis ACL - If you are using Redis version 6+, you can leverage the feature of using ACL(Access Control Lists). You can create users with passwords for each app and pass these credentials while making Redis connection. You can even add permissions/commands etc. to the users.
Data in different DB cannot be accessed i.e. if you make connection to DB 0, you cannot fetch data from DB 1.
I have large number of key-value pairs of different types to be stored in Redis cache. Currently I use a single Redis node. When my app server starts, it reads a lot of this data in bulk (using mget) to cache it in memory.
To scale up Redis further, I want to set up a cluster. I understand that in cluster mode, I cannot use mget or mset if keys are stored on different slots.
How can I distribute data into different nodes/slots and still be able to read/write in bulk?
It's handled in redis client library. You need to find if a library exists with this feature in the language of your choice. For example, if you are using golang - per docs redis-go-cluster provides this feature.
https://redis.io/topics/cluster-tutorial
redis-go-cluster is an implementation of Redis Cluster for the Go language using the Redigo library client as the base client. Implements MGET/MSET via result aggregation.
Is there an efficient method to count specific class of keys on a Redis cluster?
Here, 'specific class of keys' means the keys that are used for a common purpose; for example, session keys. They can have a common key name prefix. There can be multiple classes. From now, I will refer the class of keys as simply the keys.
What I want to do is as follows:
Redis cluster must be used.
The keys must be distributed to the nodes of the Redis cluster.
There must be an efficient way to count the number of the keys on all of the nodes of the Redis cluster.
The keys can have TTL - that is, can expire.
The number of the nodes of the Redis cluster can be changed on runtime, and hash slots can be redistributed.
Clients are implemented using Node.js.
I've read the documentation, but could not find a proper solution.
Thanks in advance.
No, basically. That doesn't exist for "classic" (non-cluster), either. To do that without an additional storage mechanism, you would need to use SCAN repeatedly to iterate over the entire keyspace. Fortunately it does at least accept a filter (so you don't need to fetch every key), but is far from efficient - you'd typically only do this periodically as a review feature, not an operational feature. We actually include such a feature in "opserver"'s redis plugin.
When you switch to cluster, you'd need to repeat this but on one of each set of replication verticals. You would typically get that list via the CLUSTER commands, so the dynamic nature of the nodes is moot.
In both classic and cluster, it would be recommended to only do this on a replica - not the master. And again: only as an admin tool, not as a routine part of your system.
Do not use KEYS to do this. Prefer SCAN.
Scenario: Two instances of an application share the same redis instance, but use different databases. The application makes use of the redis pub/sub functions to exchange data between services.
Problem: When application instance A publishes something (on redis database 1), application instance B (running on redis database 2) receives the message.
Expectation: As both instances of the application use a different database, I would expect not only that the keys in redis are hold separately, but pub/sub subscribers aswell.
Question: Can I tell redis to keep pub/sub separate for each database?
No - PubSub is shared across all clients connected to the server, regardless of their currently SELECTed database (shared database/numbered database/keyspace). While you can use different channels and such, real separation is possible only by using two Redis instances.
Note: using shared/numbered databases isn't recommended - always use dedicated Redis instances per app/service/use case
As https://redis.io/docs/manual/pubsub/#database--scoping suggests
If you need scoping of some kind, prefix the channels with the name of
the environment (test, staging, production...).
We are using redis. We have two set of data. One set of data(Assume it is using the prefix redis:local: eg: redis:local:key1) is used by the main application and no need of replication.
Another set of data (Prefix redis:replicate: eg: redis:replicate:key2) is used by the main application and should be replicated to slave redis instances.
I have two questions.
Is it possible to configure redis to replicate only keys with prefix redis:replicate:?
If that is not possible, Is it possible to configure redis to replicate only one database? We will store the first set of data in database-0 and the second set of data in database-1. So we have to replicate only database-1.
Currenly, we are running two instances of redis to solve the issue.
Redis only supports replication of whole instances. Limiting replication to a key prefix or database is not possible.
Running two instances of Redis is simplest and reliable option.
Another way would be to write a custom replication program which is difficult and failure prone in comparison.
There is also another question concerning replication of only one database: Replicate a single Redis database from an instance that has multiple databases