StackExchange.Redis学习笔记(⼆)Redis查询五种数据类型的应⽤ConnectionMultiplexer
ConnectionMultiplexer 是StackExchange.Redis的核⼼对象,⽤这个类的实例来进⾏Redis的⼀系列操作,对于⼀个整个应⽤程序应该只有⼀个ConnectionMultiplexer 类的实例。上⼀章中StackExchangeRedisHelper 的相关代码如下
private static ConnectionMultiplexer _instance = null;
///<summary>
///使⽤⼀个静态属性来返回已连接的实例,如下列中所⽰。这样,⼀旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
///</summary>
public static ConnectionMultiplexer Instance
{
get
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null || !_instance.IsConnected)
{
_instance = ConnectionMultiplexer.Connect(Coonstr);
}
}
}
/
/注册如下事件
_instance.ConnectionFailed += MuxerConnectionFailed;
_instance.ConnectionRestored += MuxerConnectionRestored;
_instance.ErrorMessage += MuxerErrorMessage;
_instance.ConfigurationChanged += MuxerConfigurationChanged;
_instance.HashSlotMoved += MuxerHashSlotMoved;
_instance.InternalError += MuxerInternalError;
return _instance;
}
}
String
 string类型应该是最长⽤到的了,⽤法也很简单,下⾯展⽰了⽤Redis来进⾏基本的字符串数字存储
public static IDatabase GetDatabase()
{
return Instance.GetDatabase();
}
///<summary>
///设置缓存
///</summary>
///<param name="key"></param>
///<param name="value"></param>
public static void Set(string key, object value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags flags = CommandFlags.None)        {
key = MergeKey(key);
GetDatabase().StringSet(key, Serialize(value), expiry, when, flags);
}
///<summary>
///根据key获取缓存对象
///</summary>
///<typeparam name="T"></typeparam>
///<param name="key"></param>
///<returns></returns>
public static T Get<T>(string key)
{
key = MergeKey(key);
return Deserialize<T>(GetDatabase().StringGet(key));
}
///<summary>
///移除指定key的缓存
///</summary>
///<param name="key"></param>
///<returns></returns>
public static bool Remove(string key)
{
key = MergeKey(key);
return GetDatabase().KeyDelete(key);
}
除了基本的string类型操作,Redis同时⽀持以下⼏种类型的操作
List  列表
Set  ⽆序集合
SortedSet  有序集合
Hash 哈希表
下⾯我依次来介绍下这四种类型在StackExchange.Redis中的基本⽤法
关于代码中的KeyDelete为删除对应的键,我这⾥是因为测试防⽌重复才加上的。⼤家不要误会
List
特点:有序排列,值可以重复。我们可以通过pop,push操作来从头部和尾部删除或者添加元素。这使得list既可以做栈也可以做队列需求:要求⼀条微博将最新的10条评论⽤户名字直接显⽰在主页上
实现:
public static void LatestUserTop10()
{
IDatabase db = StackExchangeRedisHelper.GetDatabase();
//模拟有⼀百名⽤户
for (int i = 1; i <= 100; i++)
{
db.ListLeftPush("user", "⽤户"+i);
//每⼀名⽤户插⼊后都只保留最后的⼗个⽤户到redis数据库中
db.ListTrim("user", 0, 9);
}
RedisValue[] userStores = db.ListRange("user");
foreach (var item in userStores)
{
Console.Write((string)item + ",");
}
db.KeyDelete("user");
Console.ReadLine();
}
Set
特点:⽆序排列,值不可重复。增加删除查询都很快。提供了取并集交集差集等⼀些有⽤的操作
需求:取两篇⽂章的评论者的交集并集差集
实现:
public void RedisSetTest()
{
IDatabase db = StackExchangeRedisHelper.GetDatabase();
for (int i = 1; i <= 20; i++)
{
db.SetAdd("⽂章1", i);
}
for (int i = 15; i <= 35; i++)
{
db.SetAdd("⽂章2", i);
}
RedisValue[] inter = db.SetCombine(SetOperation.Intersect, "⽂章1", "⽂章2");
RedisValue[] union = db.SetCombine(SetOperation.Union, "⽂章1", "⽂章2");
RedisValue[] dif1 = db.SetCombine(SetOperation.Difference, "⽂章1", "⽂章2");
RedisValue[] dif2 = db.SetCombine(SetOperation.Difference, "⽂章2", "⽂章1");
int x = 0;
Console.WriteLine("两篇⽂章都评论过的⽤户");
foreach (var item in inter.OrderBy(m => m).ToList())
{
Console.Write((string)item + "");
}
Console.WriteLine("\n评论过两篇⽂章中任意⼀篇⽂章的⽤户");
foreach (var item in union.OrderBy(m => m).ToList())
{
Console.Write((string)item + "");
}
Console.WriteLine("\n只评论过其第⼀篇⽂章的⽤户");
foreach (var item in dif1.OrderBy(m => m).ToList())
{
Console.Write((string)item + "");
}
Console.WriteLine("\n只评论过其第⼆篇⽂章的⽤户");
foreach (var item in dif2.OrderBy(m => m).ToList())
{
Console.Write((string)item + "");
}
db.KeyDelete("⽂章1");
db.KeyDelete("⽂章2");
Console.ReadLine();
}
SortedSet
特点:有序排列,值不可重复。类似Set,不同的是sortedset的每个元素都会关联⼀个double类型的score,⽤此元素来进⾏排序需求:显⽰⽂章被赞最多的⼗条评论
实现:
public void HotestUserTop10()
{
IDatabase db = StackExchangeRedisHelper.GetDatabase();
//模拟有⼀百名评论者,开始每个⽤户被“赞”的次数为1
List<SortedSetEntry> entrys = new List<SortedSetEntry>();
for (int i = 1; i <= 100; i++)
{
db.SortedSetAdd("⽂章1", "评论者" + i, 1);
}
//评论者2⼜被赞了两次
db.SortedSetIncrement("⽂章1", "评论者2", 2); //对应的值的score+2
//评论者101被赞了4次
db.SortedSetIncrement("⽂章1", "评论者101", 4);  //若不存在该值,则插⼊⼀个新的
RedisValue[] userStores = db.SortedSetRangeByRank("⽂章1", 0, 10, Order.Descending);
for (int i = 0; i < userStores.Length; i++)
{
Console.WriteLine(userStores[i]+":"+ db.SortedSetScore("⽂章1", userStores[i]));
}
db.KeyDelete("⽂章1");
Console.ReadLine();
}
Hash
特点:Hash是⼀个string类型的field和value的对应表,它更适合来存储对象,相⽐于每个属性进⾏⼀次缓存,利⽤hash来存储整个对象会占⽤更⼩的内存。但是存储速度并不会更快
需求:存储⼀个学⽣的基本信息redis支持的五种数据类型
实现:
public void RedisHashTest()
{
IDatabase db = StackExchangeRedisHelper.GetDatabase();
db.HashSet("student1", "name", "张三");
db.HashSet("student1", "age", 12);
db.HashSet("student1", "class", "五年级");
Console.WriteLine(db.HashGet("student1", "name"));
RedisValue[] result = db.HashGet("student1", new RedisValue[] { "name", "age","class" });
Console.WriteLine(string.Join(",",result));
db.KeyDelete("student1");
Console.ReadLine();
}
以下代码是我分别⽤stringset和hash来存储对象进⾏的时间及内存⽐较,内存可通过redis的info命令来查看。
最终显⽰耗时⽅⾯stringset稍微快⼀点点,内存占⽤stringset却是hash的⼆倍
public void RedisHashVsStringSet()
{
IDatabase db = StackExchangeRedisHelper.GetDatabase();
Stopwatch sw = new Stopwatch();
sw.Start();
//for (int i = 0; i < 100000; i++)
//{
//    db.HashSet("studenths" + i, "name", "张三" + i);
//    db.HashSet("studenths" + i, "age", 12 + i);
//    db.HashSet("studenths" + i, "class", "五年级" + i);
//}
//Console.WriteLine(sw.Elapsed.TotalMilliseconds);
//sw.Restart();
for (int i = 0; i < 100000; i++)
{
db.StringSet("studentstr_name" + i, "张三" + i);
db.StringSet("studentstr_age" + i, 12 + i);
db.StringSet("studentstr_class" + i, "五年级" + i);
}
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
//for (int i = 0; i < 100000; i++)
//{
//    db.KeyDelete("studenths" + i);
//    db.KeyDelete("studentstr_name" + i);
//    db.KeyDelete("studentstr_age" + i);
//    db.KeyDelete("studentstr_class" + i);
//}
Console.ReadLine();
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。