Redis的介绍
Remote Dictionary Server(Redis)是一个基于 key-value 键值对的持久化数据库存储系统。支持多种数据结构,包括 string (字符串)、list (链表)、set (集合)、zset (sorted set --有序集合)和 hash(哈希类型)。这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
结构介绍
- string:是最常用的一种数据类型,普通的key/value存储都可以归为此类 。一个Key对应一个Value,string类型是二进制安全的。Redis的string可以包含任何数据,比如jpg图片(生成二进制)或者序列化的对象。
- list:是一个链表结构,主要功能是push与pop,获取一个范围的所有的值等,操作中key理解为链表名字。 Redis的List类型其实就是一个每个子元素都是string类型的双向链表,我们可以通过push或pop操作从链表的头部或者尾部添加删除元素,这样List既可以作为栈,又可以作为队列。它即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
- Set:是string类型的无序集合。set是通过hash table实现的,添加,删除和查找,对集合我们可以取并集,交集,差集,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。与List比较而言,set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
- ZSet:是set的一个升级版本,又被称为ZSet,它在set的基础上增加了一个顺序的属性,这一属性在添加修改。元素的时候可以指定,每次指定后,zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表,一列存 value,一列存顺序。操作中key理解为zset的名字。sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构。此外,还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
- Hash:是一个string 类型的field和value的映射表。Hash特别适合存储对象,相对于将对象的每个字段存成单个string 类型。一个对象存储在Hash类型中会占用更少的内存,并且可以更方便的存取整个对象。Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,如下图:
NET下组件
比较常用的组件有以下两种:
StackExchange.Redis
Service.Stack.Redis
现在项目中用的是:Service.Stack.Redis,不过该组件在4.0后已经是收费的,后期可能会换成StackExchange.Redis
现在主要介绍使用Service.Stack.Redis的方式,StackExchange.Redis的介绍见参见
RedisCilent
IRedisClient为操作Redis的接口,是.Net操作Redis的主要类库。这里介绍最简单的方式,直接创建Client对象。(可以创建连接池的方式更好的控制连接数)
//Redis服务器IP地址
static string localHostIP = "127.0.0.1";
//Redis服务端口号
static int redisServicePort = 6379;
static void Main(string[] args)
{
var redisClient = new RedisClient(localHostIP, redisServicePort);
Console.ReadKey();
}
String操作
简单的Set,Get
//向Redis中添加一个Key/Value对
redisClient.Set<string>("username", "edisonchou");
//从Redis中读取一个Value值
string userName = redisClient.Get<string>("username");
Console.WriteLine("The value from Redis is {0}", userName);
计数器
redisClient.IncrementValue("requestCount"); //自增1
redisClient.IncrementValueBy("requestCount",2) //制定步数增加啊
设置过期时间
redisClient.Set<string>("username", "edisonchou", DateTime.Now.AddHours(24)); //绝对过期
redisClient.Set<string>("username", "edisonchou", TimeSpan.FromMinutes(10)); //相对过期
List操作
栈的方式
redisClient.PushItemToList("userenname", "edisonchou");
redisClient.PushItemToList("userenname", "wncudchou");
redisClient.PushItemToList("userenname", "milkye");
redisClient.PushItemToList("userenname", "dickgu");
int length = redisClient.GetListCount("userenname");
for (int i = 0; i < length; i++)
{
Console.WriteLine(redisClient.PopItemFromList("userenname"));
}
队列的方式
redisClient.EnqueueItemOnList("account", "马云");
redisClient.EnqueueItemOnList("account", "马化腾");
redisClient.EnqueueItemOnList("account", "李彦宏");
int length = redisClient.GetListCount("account");
for (int i = 0; i < length; i++)
{
Console.WriteLine(redisClient.DequeueItemFromList("account")); //正常出队的方式
}
阻塞出队的方式
当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP 命令阻塞,直到等待超时或发现可弹出元素为止。后面的阻塞时间最好带上。
redisClient.BlockingDequeueItemFromList("account",TimeSpan.FromMinutes(10)); //若没有数据阻塞10分钟
Set操作
求交集,并集等
redisClient.AddItemToSet("a3", "ddd");
redisClient.AddItemToSet("a3", "ccc");
redisClient.AddItemToSet("a3", "tttt");
redisClient.AddItemToSet("a3", "sssh");
redisClient.AddItemToSet("a3", "hhhh");
redisClient.AddItemToSet("a4", "hhhh");
redisClient.AddItemToSet("a4", "h777");
Console.WriteLine("-------------求a3集合------------");
HashSet<string> hashSet = redisClient.GetAllItemsFromSet("a3");
foreach (string value in hashSet)
{
Console.WriteLine(value);
}
Console.WriteLine("-------------求并集------------");
hashSet.Clear();
hashSet = redisClient.GetUnionFromSets(new string[] { "a3", "a4" });
foreach (string value in hashSet)
{
Console.WriteLine(value);
}
Console.WriteLine("-------------求交集------------");
hashSet.Clear();
hashSet = redisClient.GetIntersectFromSets(new string[] { "a3", "a4" });
foreach (string value in hashSet)
{
Console.WriteLine(value);
}
Console.WriteLine("-------------求差集------------");
hashSet.Clear();
hashSet = redisClient.GetDifferencesFromSet("a3", new string[] { "a4" });
foreach (string value in hashSet)
{
Console.WriteLine(value);
}
ZSet操作
主要作用:排序
redisClient.AddItemToSortedSet("a5", "ffff");
redisClient.AddItemToSortedSet("a5", "bbbb");
redisClient.AddItemToSortedSet("a5", "gggg");
redisClient.AddItemToSortedSet("a5", "cccc");
redisClient.AddItemToSortedSet("a5", "waaa");
List<string> list = redisClient.GetAllItemsFromSortedSet("a5");
foreach (string str in list)
{
Console.WriteLine(str);
}
var top2 = redisClientGetRangeFromSortedSet("a5",0,1); //取前2
Hash操作
redisClient.SetEntryInHash("user", "userinfo", "cool boy");
redisClient.SetEntryInHash("user", "useraccount", "5000");
List<string> keyList = redisClient.GetHashKeys("user");
foreach (string key in keyList)
{
Console.WriteLine(key);
string value = redisClient.GetValueFromHash("user", key);
Console.WriteLine("user:{0}:{1}", key, value);
}
Service.Stack.Redis对象操作
在该组件中可以方便的操作对象,实际存储的数据结构是List+Hash
var redisUsers = redisClient.As<User>();
var yangUser = new User { Id = redisUsers.GetNextSequence(), Name = "Eric Yang" };
redisUsers.Store(yangUser);