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"
最進弄了一個公眾號,小菜技術,歡迎大家的加入