How to implement prefix match for keys in redis? - redis

I have the following set of key value pairs in Redis
"690-product-Qwaf##45" :"mens-clothing/shirts"
"690-product-Ywsg##67" :"womens-clothing/shirts"
"690-product-Wsrf#%59" : "boys-clothing/sweaters"
"690-brand-P2af##45" : "Puma"
"690-brand-Z3af&#35" : "Free People"
"690-brand-Q4af%#49" : "True Religion"
I need to fetch only the keys starting with "690-brand-" from the above set. How can I achive the same in redis?.

You can scan the keys by using the SCAN command of redis. See documentation http://redis.io/commands/scan
Example
SCAN 0 MATCH "690-brand-*"
for a node.js example see this https://stackoverflow.com/a/37405810/6265117
You can also use KEYS command if you are working on a development environment or debugging something and database is not very large.
Link - http://redis.io/commands/keys
NOTE: KEYS is not recommended for production environments.

Related

Can django-redis use dbsize?

django-redis source: https://github.com/jazzband/django-redis/tree/master/django_redis
my problem is I can not find method to get number of keys in Redis database, it call dbsize. Methods that available such as set, get, add, delete, delete_pattern, delete_many, clear, get_many, set_many, incr, decr, has_keys, keys, iter_keys, ttl, pttl, persist, expire, expire_at, pexpire, pexpire_at, lock, close, touch.
How can I used dbsize method of redis command in django-redis library?
environment:
django version : 3.2.10
django-redis: 5.2.0
I found the solution of the question
from django_redis import get_redis_connection
REDIS = get_redis_connection("default") # default is alias of redis
REDIS.dbsize() # get number of keys in the currently-selected database
this solution can use native redis command but cannot use method of django-redis plugin
WARNING: Not all pluggable clients support this feature.

Can redis Lua script contain key determined at runtime?

Look at this lua script:
local clientIds = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'LIMIT', '0', ARGV[2]);
local prefix = 'lock:';
local lockedClientIds = {};
for _, value in ipairs(clientIds)
do
lockal key = prefix .. tostring(value)
if redis.call('EXISTS', key) == 0 then
redis.call('SET', key, 'PX', ARGV[3]);
table.insert(lockedClientIds, value)
end
end
redis.pcall('ZREM', KEYS[1], unpack(lockedClientIds));
return lockedClientIds;
It takes some values from the sorted set and uses them to create keys (after some simple concatenation). I'm not sure if this is OK because according to Redis Lua tutorials, all keys should be provided in the KEYS array so should be known in compile-time, not the runtime.
All Redis commands must be analyzed before execution to determine
which keys the command will operate on. In order for this to be true
for EVAL, keys must be passed explicitly. This is useful in many ways,
but especially to make sure Redis Cluster can forward your request to
the appropriate cluster node. Note this rule is not enforced in order
to provide the user with opportunities to abuse the Redis single
instance configuration, at the cost of writing scripts not compatible
with Redis Cluster.
So does it mean, there is a risk that this will only work with a single node and when redis is distributed across many nodes it won't work?
YES, it is (highly) possible that the script will not work in cluster mode.
It will continue to work even in cluster mode only if the keys are in same hash slot. The idea of hash tags can be used for this purpose.
Note: I'm assuming, by "redis is distributed across many nodes", you are meaning Redis Cluster mode.

Spring data redis zadd command missed nx|xx|incr options

Lettuce supported zadd's NX|XX|CH|INCR options on 2015 link.
But I can't find any thing support this in Lettuce's wrapper Spring data Redis (version:2.1.5).
It seem that the only two zadd methods that DefaultZSetOperations provide can't let me use NX|XX|CH|INCR options:
Boolean add(K key, V value, double score);
Long add(K key, Set<TypedTuple<V>> tuples);
So how can I use NX|XX|CH|INCR options on Spring data redis with Lettue?
Sorry for my poor english ,Thanks.
Not completely sure if this will 100% work the same for Lettuce. For Jedis, found that we have to use redisTemplate.execute(RedisCallback). A small example of using the ch argument for indicating if any records where changed (opposed to just being added to the sorted set)
redisTemplate.execute(
(RedisCallback<Long>) connection -> connection.zSetCommands().zAdd(
leaderboardKey.getBytes(StandardCharsets.UTF_8),
membersToTuples(members),
RedisZSetCommands.ZAddArgs.empty().ch()
)
)

Targeting multiple grains in Salt minions using API

In our infrastructure, we set multiples grains on the minion including an "environment" and "app" grain.
When we use the cli, we can get the correct minions using:
salt -C "G#app:middle_tier_1 and G#environment:dev" test.ping
But if we try to use the cherrypy api, only got a result if set only one target like:
[{"client":"local","tgt_type":"grain","fun":"test.ping","tgt":"G#app:middle_tier_1"}]
or
[{"client":"local","tgt_type":"grain","fun":"test.ping","tgt":"G#environment:dev"}]
with multiples one, don't get any
[{"client":"local","tgt_type":"grain","fun":"test.ping","tgt":"G#app:middle_tier_1 and G#environment:dev"}]
[{"client":"local","tgt_type":"grain","fun":"test.ping","tgt":["G#app:middle_tier_1","G#environment:dev"]}]
According with the documentation, i can use a list in the tgt paramenter.
I have looked their documentation fairly extensively and have found no examples of this type of minion targeting.
Is this even possible, and if so, how would I go about doing it?
Extra info:
salt-master 2018.3.2 (Oxygen)
salt-api 2018.3.2 (Oxygen)
Thanks in advance!
If you want to use multiple grains, the tgt_type is compound not grains.
See: https://docs.saltstack.com/en/latest/ref/clients/#salt-s-client-interfaces, https://docs.saltstack.com/en/latest/topics/targeting/compound.html

Using Redis as Cache and C# client

I'm new to Redis and trying to figure out a simple way to use Redis as a local cache for my C# app. I've downloaded and ran the redis-server from https://github.com/MSOpenTech/redis/releases
I can successfully store a key value and retrieve it as follows:
var redisManager = new PooledRedisClientManager("localhost:6379");
using (var redis = redisManager.GetClient())
{
redis.Set("mykey_1", 15, TimeSpan.FromSeconds(3600));
// get typed value from cache
int valueFromCache = redis.Get<int>("mykey_1"); // must be =
}
I want to limit the amount of memory Redis uses on my server and I also want redis to automatically purge values when memory fills. I tried the maxmemory command but in the redus-cli program maxmemory is not found.
Will Redus automatically purge old values for me? (I assume not) and if not, is there a way that I can make the default behavior of redis do that with the Set method I'm using below?
If I'm heading down the wrong path, please let me know.
The answer to your question is described here: What does Redis do when it runs out of memory?
Basically, you set the maxmemory from the config file, and not from the redis-cli. You can also specify a maxmemory-policy, which is a set of procedures that redis executes when it runs out of the specified memory. According to that config file, there are a total of 6 policies that Redis is using when it runs out of memory:
volatile-lru -> remove the key with an expire set using an LRU algorithm
allkeys-lru -> remove any key according to the LRU algorithm
volatile-random -> remove a random key with an expire set
allkeys-random -> remove a random key, any key
volatile-ttl -> remove the key with the nearest expire time (minor TTL)
noeviction -> don't expire at all, just return an error on write operations
You can set those behaviours using the maxmemory-policy directive that you find in the LIMITS section of redis.conf file (above the maxmemory directive).
So, you can set an expire time to every key that you store in Redis (a large expire time) and also set a volatile-ttl policy. In that way, when Redis runs out of memory, the key with the smallest TTL (which is also the oldest one) is removed, according to the policy that you've set.