本篇主要使用StackExchangeRedis在.Net Core中使用Redis,使用基礎見:點擊此處。html
1.字符串類型Stringredis
字符串類型是Redis中最基本的數據類型,它能存儲任何形式的字符串,包括二進制數據。你能夠用其存儲用戶的郵箱、JSON化的對象甚至是一張圖片。一個字符串類型鍵容許存儲地得數據的最大容量是512MB。算法
字符串類型是其餘4種數據類型的基礎,其餘數據類型和字符串類型的差異從某種角度來講只是組織字符串的形式不一樣。例如,列表類型是以列表的形式組織字符串,二集合類型是以集合的形式組織字符串。數據結構
如下爲StackExchangeRedis中字符串經常使用方法及其命令:app
(1)賦值與取值異步
//方法 redisConnection.GetDatabase().StringSetAsync(key, value); redisConnection.GetDatabase().StringGetAsync(key); //命令 127.0.0.1:6379> set stringKey stringValue OK 127.0.0.1:6379> get stringKey "stringValue"
(2)返回 key 中字符串值的子字符網站
//方法 redisConnection.GetDatabase().StringGetRangeAsync(key, start, end); //命令 127.0.0.1:6379> getrange stringKey 6 10 "Value"
(3)將給定 key 的值設爲 value ,並返回 key 的舊值(old value)ui
//方法 var oldvalue = await redisConnection.GetDatabase().StringGetSetAsync(key, oldkey); //命令 127.0.0.1:6379> getset stringKey newValue "stringValue"
(4)若是 key 已經存在而且是一個字符串, APPEND 命令將指定的 value 追加到該 key 原來值(value)的末尾編碼
//方法 redisConnection.GetDatabase().StringAppendAsync(key, appendValue); //命令 127.0.0.1:6379> append stringKey append (integer) 14
2.散列類型Hashspa
Redis是採用字典結構以鍵值對的形式存儲數據的,而Hash的鍵值也是一種字典結構,其存儲了字段(field)和字段值的映射,但字段值只能是字符串,不支持其餘數據類型,不能嵌套其餘數據類型(其餘數據類型同理)。
散列類型適合存儲對象:使用對象類別和ID構成鍵名,使用字段表示對象的屬性,而字段值則存儲屬性值。例如要存儲ID爲2的汽車對象,能夠分別使用名爲color、name和price的三個字段來存儲該輛汽車的顏色、名稱和價格。
如下爲StackExchangeRedis中散列類型經常使用方法及其命令:
(1)賦值
//方法 HashEntry[] hashEntry = new HashEntry[] { new HashEntry("id",2), new HashEntry("color","red"), new HashEntry("price",200), }; redisConnection.GetDatabase().HashSetAsync("youCar", hashEntry); //命令 127.0.0.1:6379> hset myCar price 200 (integer) 1 127.0.0.1:6379> hset mCar color blue (integer) 1 127.0.0.1:6379> hset mCar name tractor (integer) 1
(2)取值
//方法 redisConnection.GetDatabase().HashGetAsync("youCar", "color"); redisConnection.GetDatabase().HashGetAllAsync("youCar"); //命令 127.0.0.1:6379> hget youCar color "red" 127.0.0.1:6379> hgetall youCar 1) "id" 2) "2" 3) "color" 4) "red" 5) "price" 6) "200"
(3)獲取全部散列類型中的字段
//方法 var keys = redisConnection.GetDatabase().HashKeys("youCar"); //命令 127.0.0.1:6379> hkeys youCar 1) "id" 2) "color" 3) "price"
3.列表List
列表類型(List)能夠存儲一個有序的字符串列表,經常使用的操做是向列表兩端添加元素,或者得到列表的一個片斷。
列表類型內部是使用雙向鏈表(double linked list)實現的,因此向列表兩段添加元素的時間複雜都爲O(1),獲取越接近兩端的元素速度就越快。這意味着即便是一個由幾千萬個元素的列表,獲取頭部或者尾部的10條記錄也是極快的。
不過使用鏈表的代價是經過索引訪問元素比較慢。因而,列表類型很適合於如社交網站的新鮮事、記錄日誌、消息隊列等,相似獲取最前幾條的數據、從列表尾部插入等場景。
如下爲StackExchangeRedis中列表類型經常使用方法及其命令:
(1)向列表兩端增長元素
//方法 redisConnection.GetDatabase().ListLeftPushAsync("myList","head1"); redisConnection.GetDatabase().ListRightPush("myList","bottom1"); //命令 127.0.0.1:6379> lpush myList head1 (integer) 1127.0.0.1:6379> rpush myList bottom1 (integer) 2
(2)從列表兩端移除並獲取一個元素
//方法 var value = redisConnection.GetDatabase().ListLeftPopAsync("myList"); var value = redisConnection.GetDatabase().ListRightPopAsync("myList"); //命令 127.0.0.1:6379> lpop myList "head1" 127.0.0.1:6379> rpop myList "bottom1" 127.0.0.1:6379> rpop myList (nil)
(3)獲取列表中的元素片斷(不刪除只獲取)
//方法 var value = redisConnection.GetDatabase().ListRangeAsync("myList",0,2); //命令 127.0.0.1:6379> lrange myList 0 2 1) "1" 2) "2" 3) "3"
4.集合Set
Redis 的 Set 是 String 類型的無序集合。集合成員是惟一的,這就意味着集合中不能出現重複的數據。經常使用的操做是向集合加入或者刪除元素、判斷某個元素是否存在等,因爲Redis 中集合是經過哈希表實現的,因此添加,刪除,查找的複雜度都是 O(1)。
最方便的是多個集合類型鍵之間還能夠進行並集、交集和差集運算。
能夠運用在共同好友、喜愛和好友推薦(交集超過閾值)等能夠運用交差並集操做的場景。
如下爲StackExchangeRedis中集合類型經常使用方法及其命令:
(1)增長/刪除元素(可多個,相同元素自動忽略)
//方法 redisConnection.GetDatabase().SetAddAsync("mySet", new RedisValue[] { "a", "b" }); redisConnection.GetDatabase().SetRemoveAsync("mySet", "a"); //命令 127.0.0.1:6379> sadd mySet a (integer) 1 127.0.0.1:6379> sadd mySet a b c (integer) 2 127.0.0.1:6379> srem mySet c (integer) 1 127.0.0.1:6379> srem mySet b a (integer) 2
(2)獲取交集
//方法 var value = redisConnection.GetDatabase().SetCombine(SetOperation.Intersect, "mySet1", "mySet2"); //命令 127.0.0.1:6379> sadd mySet1 a b c (integer) 3 127.0.0.1:6379> sadd mySet2 b c d (integer) 3 127.0.0.1:6379> sinter mySet1 mySet2 1) "c" 2) "b"
5.有序集合Sort Set
從有序集合的名字就能夠看出它和集合的區別就是」有序「二字。
在集合類型的基礎尚有序集合類型爲集合中的每一個元素都關聯了一個分數,按分數大小進行從小到大的排序,這使得咱們不只能夠完成插入、刪除和判斷元素是否在等集合類型支持的操做,還可以得到分數最高(或最低)的前N個元素、得到指定分數範圍內的元素等與分數有關的操做。雖然集合中每一個元素都是不一樣的,可是它們的分數卻能夠相同。
有序集合類型在某方面和列表類型有些類似
兩者都是有序。
兩者均可以獲取某一範圍的元素
可是兩者由這很大的區別,這使得他們的應用場景有所不一樣。
列表是經過鏈表實現的,獲取靠近兩端的數據速度極快,而當元素增多後,訪問中間元素的速度會較慢,因此它更加適合實現如「新鮮事」或「日誌」這樣不多訪問中間元素的應用。
有序集合是使用散列表和跳錶(skip list)實現的,因此即便讀取文娛中間部分的數據速度也快(時間複雜度是O(log(N)))。
列表中不能簡單地調整元素的位置,但有序集合能夠(經過更改元素的分數),因此能夠用於排行榜、權重應用(有權重的消息隊列)。
有序集合要比類別更耗內存。
如下爲StackExchangeRedis中有序集合類型經常使用方法及其命令:
(1)增長元素
//方法 SortedSetEntry[] sortedSetEntry = new SortedSetEntry[] { new SortedSetEntry("tom",10), new SortedSetEntry("peter",20), new SortedSetEntry("david",30), }; redisConnection.GetDatabase().SortedSetAddAsync("mySs", sortedSetEntry); //命令 127.0.0.1:6379> zadd mySs 10 tom 20 peter 30 david (integer) 3
(2)獲取排名在某個分數範圍的元素列表
//方法 var value = redisConnection.GetDatabase().SortedSetRemoveRangeByScoreAsync("mySs", 10, 20); //命令 127.0.0.1:6379> zrangebyscore mySs 10 20 1) "tom" 2) "peter"
(3)增長某個元素的分數
//方法 var sorce = redisConnection.GetDatabase().SortedSetIncrementAsync("mySs", "top", 3); //命令 127.0.0.1:6379> zincrby mySs 3 tom "13"
6.小結
上面各種型所舉得例子有限,基本全部的Redis命令在StackExchangeRedis中都有相應的異步和同步的方法,你們能夠參考https://redis.io/commands。
1.HyperLogLog
Redis 在 2.8.9 版本添加了 HyperLogLog 結構(其自己也是一種算法)。
Redis HyperLogLog 是用來作基數統計的算法,HyperLogLog 的優勢是,在輸入元素的數量或者體積很是很是大時,計算基數所需的空間老是固定 的、而且是很小的。
在 Redis 裏面,每一個 HyperLogLog 鍵只須要花費 12 KB 內存,就能夠計算接近 2^64 個不一樣元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合造成鮮明對比。
可是,由於 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素自己,因此 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
因此主要應用於:
統計訪問IP數量;
統計搜索關鍵詞數量;
統計用戶在線數;
等等大數量統計。
如下爲StackExchangeRedis中經常使用方法及其命令:
(1)添加指定元素到 HyperLogLog 中
//方法 RedisValue[] redisValue = new RedisValue[] { 110,120,130,130 }; redisConnection.GetDatabase().HyperLogLogAddAsync("key", redisValue); //命令 127.0.0.1:6379> pfadd hyperlogKy 110 120 130 130 (integer) 1
(2)返回給定 HyperLogLog 的基數估算值。
//方法 var count = redisConnection.GetDatabase().HyperLogLogLength("key"); //命令 127.0.0.1:6379> pfcount hyperlogKy (integer) 3
2.geo
Redis在3.2版本以後新增了一個geo(地理位置),其數據結構爲有序集合sort set。
geo能夠將地理位置信息(經緯度)儲存起來,並計算兩個地理座標之間的位置、返回以指定位置爲圓心指定半徑內的全部地理位置信息等。
像是咱們平時的打車、租房地圖等功能中就能夠用到。
既然前面說到geo是有序集合那它的score怎麼來?是咱們本身輸入嘛?實際上是經過咱們存儲的經緯度經過geohash計算後的base32編碼字符串。geohash原理點擊此處。
如下爲StackExchangeRedis中經常使用方法及其命令:
(1)添加地理位置
//方法 GeoEntry[] geoEntry = new GeoEntry[] { new GeoEntry(120.20000, 30.26667, "hangzhou"), new GeoEntry(116.41667, 39.91667, "beijing"), new GeoEntry(121.47, 31.23, "shanghai"), }; redisConnection.GetDatabase().GeoAdd("city", geoEntry); //命令 127.0.0.1:6379> geoadd city 120.20000 30.26667 hangzhou 116.41667 39.91667 beijing 121.47 31.23 shanghai (integer) 3
(2)獲取geohash
//方法 var geohash = redisConnection.GetDatabase().GeoHash("city", "hanghzou"); //命令 127.0.0.1:6379> geohash city hangzhou 1) "wtmkpjyuph0"
(3)獲取指定元素範圍的地理信息位置集合
//方法 var geo = redisConnection.GetDatabase().GeoRadius("city", "hanghzou", 300, GeoUnit.Kilometers, 10, Order.Ascending, GeoRadiusOptions.WithGeoHash); //命令 127.0.0.1:6379> georadiusbymember city hangzhou 300 km withcoord withdist withhash asc count 10 1) 1) "hangzhou" 2) "0.0000" 3) (integer) 4054134205316048 4) 1) "120.20000249147415" 2) "30.266670658987586" 2) 1) "shanghai" 2) "161.9183" 3) (integer) 4054803462927619 4) 1) "121.47000163793564" 2) "31.229999039757836"
在給定如下可選項時, 命令會返回額外的信息:
WITHDIST : 在返回位置元素的同時, 將位置元素與中心之間的距離也一併返回。 距離的單位和用戶給定的範圍單位保持一致。
WITHCOORD : 將位置元素的經度和維度也一併返回。
WITHHASH : 以 52 位有符號整數的形式, 返回位置元素通過原始 geohash 編碼的有序集合分值。
ASC : 根據中心的位置, 按照從近到遠的方式返回位置元素。DESC : 根據中心的位置, 按照從遠到近的方式返回位置元素。
它還有個相似的georadius命令,區別是由給定的經緯度爲圓心。
//方法 var geo = redisConnection.GetDatabase().GeoDistance("city", "hanghzou","beijing"); //命令 127.0.0.1:6379> geodist city hangzhou beijing km "1126.8937"
3.發佈訂閱pub/sub
"發佈/訂閱"模式中包含兩種角色,分別是發佈者和訂閱者。訂閱者能夠訂閱一個或者若干個頻道(channel),而發佈者能夠向指定的頻道發送消息,全部訂閱此頻道的訂閱者都會收到此消息。
發佈者經過publish命令發送消息:
//命令 127.0.0.1:6379> publish channel_1 hi (integer) 0 //方法 var count = redisConnection.GetSubscriber().Publish("channel_1", "hi");
消息是發送出去了,publish命令的返回值表示接收到這條消息的訂閱者數量。由於當前沒有訂閱這訂閱這個頻道,因此返回0。
注意,發送出去的消息是不會持久化的,訂閱者只能收到訂閱以後發佈者發送的消息。
訂閱者經過subscribe命令訂閱一個或者多個頻道:
//命令 127.0.0.1:6379> subscribe channel_1 channel_2 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel_1" 3) (integer) 1 1) "subscribe" 2) "channel_2" 3) (integer) 2 1) "message" 2) "channel_1" 3) "hi" //方法 while (true) { redisConnection.GetSubscriber().Subscribe("channel_1", (channel, message) => { var msg = message;//收到的消息 var chan = channel;//頻道名稱 }); }
執行subscribe命令以後進入訂閱狀態,可能收到三種類型的回覆。每種類型的回覆都包含三個值,第一個值是消息的類型,根據消息類型的不一樣,第2、三個值得含義也不一樣。消息類型可能得取值有如下三個:
subscribe:表示訂閱成功得反饋信息。第二個值是訂閱成功得頻道名稱,第三個值是當前客戶端訂閱得頻道數量。
message:這個類型得回覆是咱們最關心得,它表示接收到得消息。第二個值表示禪師消息的頻道名稱,第三個值是消息的內容。
unsubscribe:表示成功取消訂閱某個頻道。第二個值是對應頻道的名稱,第三個值是當前客戶端訂閱的頻道數量。
StackExchangeRedis中用到message和unsubscribe這兩種。
除了經過頻道名以外,還可使用psubscribe命令經過規則訂閱頻道。如約定規則爲channel_?*則能夠匹配channel_爲開頭的頻道,如channel_一、channel_2等。
//命令 127.0.0.1:6379> psubscribe cahnnel_?* Reading messages... (press Ctrl-C to quit) (integer) 1 1) "psubscribe" 2) "cahnnel_?*" 3) (integer) 1 //方法 while (true) { redisConnection.GetSubscriber().Subscribe("channel_?*", (channel, message) => { var msg = message;//收到的消息 var chan = channel;//頻道名稱 }); }
解除訂閱經過命令unsubscribe,若是不指定頻道則取消所有訂閱。在StackExchangeRedis中分別時方法Unsubscribe()和UnsubscribeAll()。