redis的安裝與五種結構的使用

  • 2019 年 10 月 16 日
  • 筆記

  這次我們來說說我們的redis,在我們的redis的認知里,最熟悉的就是用redis作為緩存使用,還有我們的分佈式session,其實還有很多redis的使用,還有redis的哨兵模式等等。

  Redis(全稱:Remote Dictionary Server 遠程字典服務)是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。(百度百科)

安裝(linux為例講解)

  1.先安裝一下C語言的包,redis的底層是用C來寫的,如果不安裝可能安裝的時候會報錯的。輸入$ yum install gcc

  2.獲得redis資源,輸入 $ wget http://download.redis.io/releases/redis-5.0.5.tar.gz

  3.開始安裝,輸入以下命令即可

  $ tar -zxvf redis-5.0.5.tar.gz;

  $ cd redis-5.0.5;

  $ make 

  4.修改配置,直接輸入vim redis.conf,然後跳轉到136行(差不多就是136行,版本不同文件可能存在差異),daemonize no設置為daemonize yes,

  5.啟動,輸入./src/redis-server redis.conf 即可啟動了,輸入ps -ef|grep redis可以看到redis是否啟動成功。

  6.輸入./src/redis-cli 即可進入客戶端,quit退出。

 官網有如何安裝的教程這裡就不在繼續贅述了。

redis的數據結構:

   我們都知道redis是鍵值對的形式來存儲數據的,其實內部還有幾種結構的,也是我們常見常用的結構,這裡來詳細說一下。

 

 我們接下來會圍繞這五種數據結構來展開去講。

結構與常見命令場景

String常見操作

SET KEY VALUE //存入單個字符串鍵值對,最常見不過了,單值緩存,就不說啦。

MSET KEY VALUE//批量寫入字符串,一般來存對象。看下實例

這裡有一張職員表,內容如下

 只存了姓名和年齡兩個字段,以前我們的方式都是設置一個key,然後把姓名和年齡轉為json然後再存儲對吧。

我們來看一下我們的MSet命令是如何使用並存儲的。

mset user:1:name zhang user:1:age 1

也就是說我們一口氣直接把user表內id為1的對象都存在了redis里,然後我們用mget user:1:name user:1:age。就可以一次性取出來了。

SETNX //存入一個不存在的字符串鍵值對,我們來看一下實例。最簡單的分佈式鎖就看可以用他來實現。

 127.0.0.1:6379> setnx lock:user true  (integer) 1  127.0.0.1:6379> setnx lock:user true  (integer) 0

就是說只允許一次的寫入,寫入成功才會返回1,否則是0,我們的線程爭搶就看誰優先寫入啦。

GET KEY//取得一個鍵對應的字符串,上文提到過 ,不再贅述

MGET KEY//批量獲得鍵對應的字符串,上文提到過 ,不再贅述

EXPIRE KEY SECONDS //設置一個鍵的過期時間,單位是秒

127.0.0.1:6379> expire lock:user 1  (integer) 1  127.0.0.1:6379> get lock:user  (nil)

原子加減

INCR key //將key中存儲的數字值加1,一般用在新聞點贊計數操作 incr {文章:id}

 

127.0.0.1:6379> incr article:xiaocai   (integer) 1  127.0.0.1:6379> incr article:xiaocai   (integer) 2  127.0.0.1:6379> incr article:xiaocai   (integer) 3  127.0.0.1:6379> incr article:xiaocai   (integer) 4

 

DECR key //將key中存儲的數字值減1,一般用在新聞點贊計數操作

INCRBY KEY  increment //將key所存儲的值加上increment

DECRBY key decrement //將key所存儲的值減去decrement


 哈希Hash常見操作

  hash結構和我們的String有些不同,原本String是一個key對應一個value,而我們的hash是一個redis_key,對應一組值,內部還有hash_key對應我們的hash_value。但是用法幾乎是一致

hset key hash_key  hash_value //存儲一個hash表的key的鍵值對

127.0.0.1:6379> hset user 1:name zhao  (integer) 0  127.0.0.1:6379> hget user 1:name  "zhao"

hsetnx key hash_key  hash_value //存儲一個不存在的hash表的key的鍵值對 

127.0.0.1:6379> hsetnx lock user:locak true  (integer) 1  127.0.0.1:6379> hsetnx lock user:locak true  (integer) 0

hmset key hash_key  hash_value //存儲一個hash表的多個key的鍵值對

127.0.0.1:6379> hmset user 1:name zhoao 1:age 11  OK  127.0.0.1:6379> hmget user 1:name 1:age  1) "zhoao"  2) "11"

hget key hash_key //獲取哈希表key對應的多個hash鍵值

hdel key hash_key //刪除哈希表key中的hash鍵值對

hlen key //返回所有哈希表key中該鍵的數量

127.0.0.1:6379> hlen user  (integer) 2

hgetall key //返回所有哈希表key中所有鍵的鍵值對

127.0.0.1:6379> hgetall user  1) "1:name"  2) "zhoao"  3) "1:age"  4) "11"

hash哈希的有點在於,對於同類的數據更好的整合在了一起,方便數據的管理,相比String操作消耗的內存與cpu更小(以後會詳細說明為什麼小),空間佔用也是比String要小的,但在集群的架構下不適合大規模的使用。


 列表常見操作

lpush key value //將一個或者多個值value插入到key列表的最左邊left 

127.0.0.1:6379> lpush liredis a  (integer) 1  127.0.0.1:6379> lpush liredis b  (integer) 2  127.0.0.1:6379> lpush liredis c  (integer) 3

rpush key value //將一個或者多個值value插入到key列表的最右邊right

127.0.0.1:6379> rpush liredis 1  (integer) 4  127.0.0.1:6379> rpush liredis 2  (integer) 5  127.0.0.1:6379> rpush liredis 3  (integer) 6

lpop key //移除並返回對應key的頭元素(最左邊的元素)

127.0.0.1:6379> lpop liredis  "c"

rpop key  //移除並返回對應key的尾元素(最右邊的元素)

127.0.0.1:6379> rpop liredis  "3" 

lrange key start stop //返回列表key中start到stop的區間元素,需要注意的是角標是從0開始的,start和stop都包含在內的,不如我們輸入  lrange redis_key 0 2 ,則表示取得第0,1,2三個元素。

127.0.0.1:6379> lrange liredis 1  2  1) "a"  2) "1"

blpop key timeout //從列表key的表頭(最左側)彈出第一個元素,若隊列中沒有元素,阻塞等待timeout秒,如果timeout=0,一直等待

127.0.0.1:6379> blpop liredis 1  1) "liredis"  2) "b"  127.0.0.1:6379> blpop liredis 1  1) "liredis"  2) "a"  127.0.0.1:6379> blpop liredis 1  1) "liredis"  2) "1"  127.0.0.1:6379> blpop liredis 1  1) "liredis"  2) "2"  127.0.0.1:6379> blpop liredis 1  (nil)  (1.04s)

brpop key timeout //從列表key的表尾(最右側)彈出末尾元素,若隊列中沒有元素,阻塞等待timeout秒,如果timeout=0,一直等待

更好的理解我們的列表命令,我們可以從數據結構的角度來說一下。

棧:先進先出,也就是我們的Lpush+lpop,或者rpush+rpop就可以實現的。

隊列:先進後出,也就是我們的Lpush+rpop,或者rpush+lpop就可以實現的。

阻塞隊列:lpush+brpop也就可以實現啦。


set集合常見操作

sadd key member //往集合key中存入元素,元素存在則忽略

127.0.0.1:6379> sadd setredis 1 2 3 4 5  (integer) 5  127.0.0.1:6379> sadd setredis 1 2  (integer) 0

srem key member //從集合key中刪除元素

127.0.0.1:6379> srem setredis a  (integer) 0  127.0.0.1:6379> srem setredis 1  (integer) 1

smembers key //獲取集合中的所有元素

127.0.0.1:6379> smembers setredis  1) "2"  2) "3"  3) "4"  4) "5"

scard key //獲取集合key中的元素個數

127.0.0.1:6379> scard setredis  (integer) 4

sismember key member //判斷member元素是否存在於集合key中 

127.0.0.1:6379> sismember setredis a  (integer) 0  127.0.0.1:6379> sismember setredis 2  (integer) 1

srandmember key count //從集合key中選出count個元素,元素不從key中刪除

127.0.0.1:6379> srandmember setredis 2  1) "5"  2) "4"

spop key count //從集合key中選出count個元素,元素從key中刪除,抽獎小程序可以使用這個。

127.0.0.1:6379> spop setredis 1  1) "4"  127.0.0.1:6379> smembers setredis  1) "2"  2) "3"  3) "5"

 集合的運算,我們在高中數學第一節課的時候就講過集合(我們當時高中第一節講的就是集合),不知道大家還記得交集並集補集都是什麼意思嗎?

sinter keyA keyB //集合keyA和集合B的交集,就是求既在集合A也在集合B內的元素

127.0.0.1:6379> sadd setA 1 2 3 4 5 6  (integer) 6  127.0.0.1:6379> sadd setB 5 6 7 9 10  (integer) 5  127.0.0.1:6379> sinter setA setB  1) "5"  2) "6"

sinterstore destination keyA keyB //將交集的結果存在新的集合destination中

 

127.0.0.1:6379> SINTERSTORE newset setA setB  (integer) 2  127.0.0.1:6379> smembers newset  1) "5"  2) "6"

 

sunion keyA keyB //得到集合A和集合B的並集結果  

127.0.0.1:6379> SUNION setA setB  1) "1"  2) "2"  3) "3"  4) "4"  5) "5"  6) "6"  7) "7"  8) "9"  9) "10"

sunionstore  destination keyA keyB //將並集的結果存在新的集合destination中

sdiff keyA keyB //求集合A對於集合B的差集,也就是{A}-{B},更通俗一點說就是存在於集合A的,但是不存在於集合B的元素。

127.0.0.1:6379> smembers setA  1) "1"  2) "2"  3) "3"  4) "4"  5) "5"  6) "6"  127.0.0.1:6379> smembers setB  1) "5"  2) "6"  3) "7"  4) "9"  5) "10"  127.0.0.1:6379> sdiff setA setB  1) "1"  2) "2"  3) "3"  4) "4"

sdiffstore  destination keyA keyB //將差集的結果存在新的集合destination中

擴展:如果我們是sdiff keyA keyB keyC //這裡就表示{A}-{B}-{C}。不要琢磨什麼這是A對於B和C並集的差集…亂不亂,自己都懵圈的。

集合A:[1,2,3,4,5,6]

集合B:[2,3,4]

集合C:[5,7,9]

這時我們輸入sdiff keyA keyB keyC他的返回應該是[1,6]。因為{A}-{B}為{1,5,6},在用這個集合去掉C包含的元素,也就是5,最終得到集合[1,6]


 有序zSet常見操作

zadd key score member score member //往有序集合key中加入帶score分值的元素

127.0.0.1:6379> zadd zsetredis 1 zhaor 2 qian  (integer) 2

zrem key member //從有序集合key中刪除元素

127.0.0.1:6379> zrem zsetredis zhaor  (integer) 1

zscore key member //返回有序集合key中元素member的分值

127.0.0.1:6379> zscore zsetredis qian  "2"

zincrby key increment menber //為有序集合key中元素member的分值加上increment數值

127.0.0.1:6379> ZINCRBY zsetredis 10 qian  "12" 

ZCARD key //返回有序集合key中的元素個數

127.0.0.1:6379> ZCARD zsetredis  (integer) 2 

zrange key start stop withscores//正序獲取有序集合內從 start到stop下標的元素,加了withscores展示分值

127.0.0.1:6379> zrange zsetredis  0 999  1) "zhao"  2) "qian"

zrevrange key  start stop withscores//倒序獲取有序集合內從 start到stop下標的元素,加了withscores展示分值

127.0.0.1:6379> ZREVRANGE zsetredis 0 999  1) "qian"  2) "zhao"

正序倒序都是按照分值來排序的

zSet運算

zunioonstore destkey numkeys keyA keyB //求集合A和集合B的並集

127.0.0.1:6379> ZUNIONSTORE newzset 2 zsetA zsetb  (integer) 4  127.0.0.1:6379> ZRANGE newzset 0  1111  1) "wuliu"  2) "zhaogsan"  3) "wangwu"  4) "lisi"

zinterstore destkey numkeys KeyA keyB //求集合A和集合B的交集,只看元素,不看分值。

127.0.0.1:6379> ZINTERSTORE newset 2 zsetA zsetb  (integer) 1  127.0.0.1:6379> zrange  newset  0 1111  1) "lisi"


 最進弄了一個公眾號,小菜技術,歡迎大家的加入