How to pipeline multiple read commands to Redis us

2020-07-25 12:45发布

问题:

Using ServiceStack, is there a way to perform multiple read commands (in particular the ContainsKey command)?

The objects stored take a while to fetch from the database, so we're looking to get only the ones that are not in cache.

I know that I can ask redis for the object and then fetch from the database if it comes back null, but the objects being stored are fairly large, so I'd rather just get a list of bools back and then determine which ids to query in the database from that.

For the time being I'm looping through my list of Ids (can be up to 100 or so) and using the ContainsKey method in servicestack. I'm looking to avoid all of the back and forth and make all of the requests in one shot.

回答1:

On the ServiceStack.Redis client you can use GetValues or GetValuesMap (both string and T apis are available) for fetching multiple values (uses MGET) in a single call. Only existing items are returned, which you can detect with GetValues if you have Id's on your models or GetValuesMap which returns a dictionary of existing keys and their values.

From this, you can determine and fetch all the missing Ids from the database. If you're just going to fetch the existing values from Redis anyway, then this is the most optimal strategy since you can fetch all the values and determine the existing keys with 1 call.

Alternative 'Single Call' options

Use Pipelining or Transactions

If for some reason you really only want to check the existence of keys in Redis without fetching them, then you can use a Transaction / or Pipeline (both are pipelined) to queue up multiple operations that gets sent to Redis in 1 socket write. Here's an example of this from RedisStackOverflow demo that queues up 30 operations that gets send and executed in a single batch.

Use LUA Scripting

If you have Redis >v2.5x you can create and execute composite operations using Redis's server-side LUA support. You can use these APIs from IRedisClient in ServiceStack.Redis client to execute server-side LUA scripts:

string GetEvalStr(string body, int numOfArgs, params string[] args);
int GetEvalInt(string body, int numOfArgs, params string[] args);
List<string> GetEvalMultiData(string body, int numOfArgs, params string[] args);