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);