Redis C# 驱动 StackExchange.Redis 应用实例
StackExchange.Redis 是一个不错的 Redis C# 驱动,使用起来也相对比较简单。
1> 引用 StackExchange.redis
PM> Install-Package StackExchange.Redis
2> StackExchange.redsi 应用实例
由于 Redis 采用单线程单进程模型,所以 Redis 连接实例可以用单例来实现;
public class RedisContextOpertion { private static ConnectionMultiplexer _redisConnection; private static object objLock = new object(); static RedisContextOpertion() { if (_redisConnection == null) { lock (objLock) { if (_redisConnection == null) { //StackExchange.redsi 支持 Redis 集群; // string connString = "127.0.0.1:6379,127.0.0.1:6380"; string connString = "127.0.0.1:6379"; _redisConnection = ConnectionMultiplexer.Connect(connString); } } } } public static ConnectionMultiplexer RedisConnection { get { return _redisConnection; } } private RedisContextOpertion() { } }
调用方法:
var conn = RedisContextOpertion.RedisConnection; var resisDb = conn.GetDatabase();
StackExchang.redis 应用实例:
A :求有序集合(Sorted Sets)差集;
构造有序集合数据源: key1,key2;
var conn = RedisContextOpertion.RedisConnection; var redisDb = conn.GetDatabase(); SortedSetEntry[] entity = new SortedSetEntry[] {new SortedSetEntry("a",100),new SortedSetEntry("b",200) }; SortedSetEntry[] entity1 = new SortedSetEntry[] { new SortedSetEntry("b", 200), new SortedSetEntry("c", 300) }; redisDb.SortedSetAdd("key1", entity, CommandFlags.None); redisDb.SortedSetAdd("key2", entity1, CommandFlags.None);
key1:
key2:
计算代码:
var conn = RedisContextOpertion.RedisConnection;
var redisDb = conn.GetDatabase();
//先求出两个集合的并集,同时设置重合项的乘法因子为 0(),设置聚合方式为取最小值;
//("weights", 1, 0)weights 为关健字,1 为key1的乘法因子,0为key2的乘法因子,有多个 key 时,以此类推;
redisDb.Execute("ZUNIONSTORE", "newkey", 2, "key1", "key2", "weights", 1, 0, "aggregate", "min");
//去除 score 为零的的元素,得到差集;
redisDb.Execute("ZREMRANGEBYSCORE", "newkey", 0, 0);
var queryResult = redisDb.SortedSetRangeByScoreWithScores("newkey");
Console.WriteLine("value\tscore");
foreach (var item in queryResult)
{
Console.WriteLine("{0}\t{1}",item.Element,item.Score);
}
计算结果:
注意事项:此方法不能在 Redis 集群环境中运行,因为 Redis 不支持跨节点调用,也就是说 Redis Cluser 不支持,带有两个或以上 key 的命令;如果想要在集群环境中应用,就必需要保证 key1 , key2 和 newkey 存放在同一个 hash 槽内,以下实例实现不同的key存放在同一个 hash 槽内;
B:Redis 集群环境中,不同 key 存放在同一 hash 槽内
其实,要想使不同的 key 存放到同一 hash 槽内是比较简单的,我们只需要使多个 key 拥有共同的部分,并用“{}”把共同的部分包裹起来就可以了。当然这样做违背了集群均衡原则,我们只在特殊情况下使用。
var conn = RedisContextOpertion.RedisConnection;
var db = redis.GetDatabase();
var entity1 = new SortedSetEntry[] { new SortedSetEntry("a", 100), new SortedSetEntry("b", 200) };
var entity2 = new SortedSetEntry[] { new SortedSetEntry("b", 200), new SortedSetEntry("c", 300) };
var commKey = "{testkey}"; // 多个 key 的共同部分;
db.SortedSetAdd(commKey + "1", entity1);
db.SortedSetAdd(commKey + "2", entity2);
C:Redis 批量添加不同类型数据;
var conn = RedisContextOpertion.RedisConnection; var db = conn.GetDatabase(); List<Task> listTask = new List<Task>(); var batch = db.CreateBatch(); listTask.Add(batch.StringSetAsync("key1", "a")); //添加字符串类型数据; listTask.Add(batch.SortedSetAddAsync("key2", "b", 1)); // 添加有序集合数据; batch.Execute(); Task.WaitAll(listTask.ToArray());
E:模糊查询,在redis里,允许模糊查询有3个通配符*、?、[]、 * : 通配任意多个字符 ?: 通配单个字符 []: 通配括号内的某1个字符
/// <summary> /// redis 模糊查询 key 是否存在; /// </summary> /// <param name="pattern"></param> /// <returns></returns> public bool KeyIsExit(string pattern) { var luaScript = "return redis.call('keys',@pattern)"; var prepared = LuaScript.Prepare(luaScript); var cacheResult = db.ScriptEvaluate(prepared, new { pattern = pattern }); if (cacheResult.IsNull) { return false; } var keys = ((string[])cacheResult).ToList(); return keys.Count > 0; }
/// <summary> /// redis 模糊查询 key 列表; /// </summary> /// <param name="pattern"></param> /// <returns></returns> public List<string> QueryMatchKeys(string pattern) { var keys = new List<string>(); var script = "return redis.call('keys',@pattern)"; var prepared = LuaScript.Prepare(script); var cacheResult = db.ScriptEvaluate(prepared, new { pattern = pattern }); if (cacheResult.IsNull) { return keys; } return ((string[])cacheResult).ToList(); }
Stack.Exchange.redis 推荐的写法;
string value = await db.StringGetAsync(key); if (value == null) { value = await ComputeValueFromDatabase(...); db.StringSet(key, value, flags: CommandFlags.FireAndForget); } return value;