新聞推薦實戰(zhàn)(三):Redis基礎(chǔ)

新聞推薦實戰(zhàn)(二):MongoDB基礎(chǔ)
本文屬于新聞推薦實戰(zhàn)—數(shù)據(jù)層—構(gòu)建物料池之Redis。Redis(Remote Dictionary Server ),即遠程字典服務(wù),是一個開源的使用ANSI C語言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫。由于是內(nèi)存數(shù)據(jù)庫,讀寫非常高速,可達10w/s的頻率,所以一般應(yīng)用于數(shù)據(jù)變化快、實時通訊、緩存等。但內(nèi)存數(shù)據(jù)庫通常要考慮機器的內(nèi)存大小。Redis 是完全開源免費的,遵守 BSD 協(xié)議,是一個靈活的高性能 key-value 數(shù)據(jù)結(jié)構(gòu)存儲,可以用來作為數(shù)據(jù)庫、緩存和消息隊列。相比于其他的 key-value 緩存產(chǎn)品有以下三個特點:
Redis 支持數(shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時候可以再次加載到內(nèi)存使用。 Redis 不僅支持簡單的 key-value 類型的數(shù)據(jù),同時還提供 list,set,zset,hash 等數(shù)據(jù)結(jié)構(gòu)的存儲。 Redis 支持主從復(fù)制,即 master-slave 模式的數(shù)據(jù)備份。
安裝Redis模塊
Python連接Redis
安裝
本項目是基于Ubuntu環(huán)境進行開發(fā),因此接下來都以Ubuntu的環(huán)境為基礎(chǔ),對于其他開發(fā)環(huán)境,大家可以參考相關(guān)的資料進行學習。
安裝Redis服務(wù)器:
sudo?apt-get?install?redis-server
下載完成的結(jié)果

啟動Redis服務(wù):
一般來說,當安裝完成后,Redis服務(wù)器會自動啟動,可以通過以下命令檢查是否啟動成功。(ps:如果Active顯示為 active(running) 狀態(tài):表示redis已在運行,啟動成功)
service?redis-server?status

檢查當前進程,查看redis是否啟動。(ps: 可以看到redis服務(wù)正在監(jiān)聽6379端口)
ps?-aux|grep?redis-server

或者進入redis客戶端,與服務(wù)器進行通信,當輸入ping命令,如果返回 PONG 表示Redis已成功安裝。
redis-cli?

上面的127.0.0.1 是redis服務(wù)器的 IP 地址,6379 是 Redis 服務(wù)器運行的端口。
命令
下面簡單介紹一些常用的Redis命令:
1、基本操作命令:
啟動Redis
redis-server?[--daemonize?yes][--port?6379]可以通過帶參數(shù)方式來啟動,如果參數(shù)過多,可以使用/etc/redis/redis.conf下面的配置文件來啟動Redis。
redis-server?/etc/redis/redis.conf連接Redis
redis-cli?[-h?host?-p?port?-a?password]其中上面參數(shù)默認的是redis-server的默認地址和端口號,password可以在服務(wù)啟動時采用參數(shù)的方式或者配置文件方式都可進行設(shè)置。因此可以通過redis-cli,可以連上我們服務(wù)器端的redis服務(wù)。
停止Redis
停止Redis有兩種方法,一種是通過 redis-cli 停止,另一種是通過殺掉redis服務(wù)進程
>?redis-cli?shutdown
>?kill?redis-pid切換庫指令
redis.conf配置中默認16個庫,下標從0~15。進入客服端默認選中第0個庫,可以通過select命令進行切換,index表示庫的小標。
127.0.0.1:6379>?SELECT?index刪除當前庫的數(shù)據(jù)
刪除當前選擇的數(shù)據(jù)庫中的所有數(shù)據(jù),這個命令永遠不會出現(xiàn)失敗。
127.0.0.1:6379[1]>?FLUSHDB?刪除所有庫的數(shù)據(jù)
刪除所有數(shù)據(jù)庫里面的數(shù)據(jù),注意是所有數(shù)據(jù)庫,這個命令永遠不會出現(xiàn)失敗。
127.0.0.1:6379[1]>?FLUSHALL查看key的數(shù)量
查看當前選擇的庫中key的數(shù)量
127.0.0.1:6379>?DBSIZE測試以上命令
neu@neu:~$?redis-server?--daemonize?yes?--port?6378?--requirepass?123456
28518:C?26?Oct?20:52:56.389?#?oO0OoO0OoO0Oo?Redis?is?starting?oO0OoO0OoO0Oo
28518:C?26?Oct?20:52:56.389?#?Redis?version=4.0.9,?bits=64,?commit=00000000,?modified=0,?pid=28518,?just?started
28518:C?26?Oct?20:52:56.389?#?Configuration?loaded
neu@neu:~$?redis-cli?-p?6378?-a?123456
127.0.0.1:6378>?set?name?jiangyou??#?在第0個數(shù)據(jù)庫插入一個值
OK
127.0.0.1:6378>?select?1??#?選擇第1個數(shù)據(jù)庫
OK
127.0.0.1:6378[1]>?set?age?26????#?在第1個數(shù)據(jù)庫插入一個值
OK
127.0.0.1:6378[1]>?DBSIZE?????#?第1個數(shù)據(jù)庫當前的key值數(shù)量
(integer)?1
127.0.0.1:6378[1]>?FLUSHDB????#?刪除第1個數(shù)據(jù)庫的所有值
OK
127.0.0.1:6378[1]>?DBSIZE?????#?刪除后數(shù)據(jù)庫中沒有值
(integer)?0
127.0.0.1:6378[1]>?SELECT?0?????#?切換到第0個數(shù)據(jù)庫
OK
127.0.0.1:6378>?DBSIZE??????#?第1個數(shù)據(jù)庫的值存在,因此FLUSHDB只刪除第1個數(shù)據(jù)庫的所有值
(integer)?1
127.0.0.1:6378>?SELECT?1????
OK
127.0.0.1:6378[1]>?FLUSHALL???#?切換到第1個數(shù)據(jù)庫,使用FLUSHALL刪除所有數(shù)據(jù)庫的值
OK
127.0.0.1:6378[1]>?SELECT?0
OK
127.0.0.1:6378>?DBSIZE????#?切換到第0個數(shù)據(jù)庫,發(fā)現(xiàn)所有的值已被刪除
(integer)?0
2、Key的操作命令:
該部分指令主要是為了對數(shù)據(jù)庫中的key進行增刪改查等一些列操作,下面主要介紹幾個常用的命令。
查找符合模板的Key
KEYS?pattern該指令查找數(shù)據(jù)庫所有符合pattern的key,其中pattern可以為?、* ?、[abc...]、[a-d]等方式。其中?代表一個任意一個字符,*代表任意0個或多個字符,[abc...]代表只能是[]中的值,[a-d]代表a到d范圍內(nèi)總的值。
127.0.0.1:6378>?keys?*
1)?"age"
2)?"school"
3)?"home"
4)?"name"
127.0.0.1:6378>?keys?*e
1)?"age"
2)?"home"
3)?"name"
127.0.0.1:6378>?keys?a?e
1)?"age"
127.0.0.1:6378>?keys?[a-n][ao]me
1)?"home"
2)?"name"
127.0.0.1:6378>?keys?[a-n][a]me
1)?"name"查找存在key的數(shù)量
EXISTS?key?or?[key…]該指令為了查找一個或多個key,返回存在key值的數(shù)量。
127.0.0.1:6378>?exists?name
(integer)?1
127.0.0.1:6378>?exists?name?home?id
(integer)?2設(shè)置過期時間
EXPIRE?key?secondsexpire 設(shè)置 key 的過期時間,時間過期后,key 會被自動刪除,設(shè)置成功返回1,key不存在返回0。
?TTL?keyttl 命令以秒為單位返回key的剩余過期時間,如果key不存在返回 -2 ?key 存在但沒有關(guān)聯(lián)超時時間則返回 -1 。
127.0.0.1:6378>?expire?name?30
(integer)?1
127.0.0.1:6378>?ttl?name
(integer)?26
127.0.0.1:6378>?ttl?name
(integer)?-2
127.0.0.1:6378>?ttl?age
(integer)?-1
127.0.0.1:6378>?ttl?id
(integer)?-2Key所屬類型
TYPE?keytype命令以字符串的形式返回存儲在
key中的值的類型,可返回的類型有:string,list,set,zset,hash和stream,如果key值不存在返回none。127.0.0.1:6378>?set?key1?"value"
OK
127.0.0.1:6378>?lpush?key2?"value"
(integer)?1
127.0.0.1:6378>?SADD?key3?"value"
(integer)?1
127.0.0.1:6378>?type?key1
string
127.0.0.1:6378>?type?key2
list
127.0.0.1:6378>?type?key3
set
127.0.0.1:6378>?type?key
none刪除Key
DEL?key?or?[key…]del命令刪除指定的key,不存在的key忽略,返回0,如果key存在,返回刪除的key的個數(shù)。
127.0.0.1:6378>?del?key
(integer)?0
127.0.0.1:6378>?del?key1?key2
(integer)?2
3、字符串類型—string命令:
字符串是Redis中最常見的數(shù)據(jù)類型,它能夠存儲任何形式的字符串,其中包括二進制格式,JSON格式,序列化格式等數(shù)據(jù)。而string相關(guān)的命令則是用于管理redis字符串值,下面介紹一些常見命令。
基礎(chǔ)命令
SET
set命令將key定為指定的字符串,如果key存在,則會覆蓋原來的值。
SET?key?value?[EX?seconds]?[PX?milliseconds]?[NX|XX]其中set可以為設(shè)定的值設(shè)置過期時間,EX表示秒數(shù),PX表示毫秒。參數(shù)NX表示只有鍵key不存在的時候才會設(shè)置key的值,XX表示只有鍵key存在的時候才會設(shè)置key的值。
GET
get命令返回與鍵
key相關(guān)聯(lián)的字符串值。GET?key如果key不存在,返回nil,如果key的值是非字符串類型,那么返回一個錯誤。
APPEND
append命令將指定的key追加值。如果key存在,并且是字符串,則會將value追加到key原值的末尾,如果key值是非字符串則會報錯,當key不存在時候,改命令類似于set,簡單將key設(shè)定為value。
APPEND?KEY_NAME?NEW_VALUEINCR
incr 命令將 key 中儲存的數(shù)字值增一。如果key不存在,key值會被初始化為0,在進行incr操作。如果字符串類型的值不能表示為數(shù)字,則會報錯。
INCR?KEY_NAME?DECR
decr命令將 key 中儲存的數(shù)字值減一,和incr命令相似。
DECR?KEY_NAME
常用命令
STRLEN
Strlen 命令將獲取指定 key 所儲存的字符串值的長度,如果key存儲的不是字符串類型或不存在時,返回錯誤。
STRLEN?KEY_NAMESETRANG
Setrange命令是將從偏移量
offset開始, 用value參數(shù)覆蓋鍵key儲存的字符串值。SETRANGE?key?offset?value不存在的鍵
key當作空白字符串處理,如果鍵key原來儲存的字符串長度比偏移量小,那么原字符和偏移量之間的空白將用零字節(jié)("\x00" )進行填充。GETRANG
Getrange命令返回存儲在 key 中的字符串的子串,由
start和end偏移決定(都包括在內(nèi))。負數(shù)偏移提供相對字符串結(jié)尾的偏移。并且該命令會通過將結(jié)果范圍限制為字符串的實際長度來處理超出范圍的請求。?GETRANGE?key?start?end當key不存在返回空字符串。
MSET
命令設(shè)置多個
key的值為各自對應(yīng)的 value。如果key存在,則會用新值替換舊值,如果key不存在,會重新創(chuàng)建,該命令總是返回“OK”,因為 MSET不會失敗。MSET?key?value?[key?value?...]MGET
命令返回所有(一個或多個)給定 key 的值,值的類型是字符串。如果給定的 key 里面有某個 key 不存在或者值不是字符串,那么這個 key 返回特殊值
nil。?MGET?key?[key?...]
測試以上命令
127.0.0.1:6379>?set?name?jiang?XX???#??XX表示只有鍵key存在的時候才會設(shè)置key的值
(nil)
127.0.0.1:6379>?set?name?jiang?NX???#??NX表示只有鍵key不存在的時候才會設(shè)置key的值
OK
127.0.0.1:6379> get name ??#??返回與鍵?`key`?相關(guān)聯(lián)的字符串值。
"jiangyou"
127.0.0.1:6379>?get?age????#??鍵key不存在的時候返回nil
(nil)
127.0.0.1:6379>?APPEND?name?????#??將value追加到key原值的末尾,返回值的總長度
(integer)?14
127.0.0.1:6379>?get?name?
"jiangyou"
127.0.0.1:6379>?set?age?24?EX?30???#??設(shè)置age?的值,并設(shè)置了過期時間??EX表示秒
OK
127.0.0.1:6379>?incr?age???????#??在age上進行增?1
(integer)?25
127.0.0.1:6379>?get?age
"25"
127.0.0.1:6379>?decr?age???????#??在age上進行減?1
(integer)?24
127.0.0.1:6379>?get?age
"24"
127.0.0.1:6379>?incr?name??????#??由于name值不能表示數(shù)字,無法增1
(error)?ERR?value?is?not?an?integer?or?out?of?range
127.0.0.1:6379>?STRLEN?name????#??name對應(yīng)的string的長度
(integer)?8
127.0.0.1:6379>?SETRANGE?name?10?hahaha?????#?從偏移量為10?的位置開始加入hahaha
(integer)?16
127.0.0.1:6379>?get?name??????????????#?不足的用\x00?補充
"jiangyou\x00\x00hahaha"
127.0.0.1:6379>?GETRANGE?name?0?-1????#?獲取name的值,改方式類似于python的數(shù)組查找
"jiangyou\x00\x00hahaha"
127.0.0.1:6379>?MSET?age?26?home?liaoning???#??為多個key賦值
OK
127.0.0.1:6379> MGET age home addr ???#???查找多個key對應(yīng)的值,不存在的key返回nil。
1)?"26"
2)?"liaoning"
3)?(nil)
4、列表—list命令:
基本命令
LPUSH
Lpush 將一個或多個值插入到列表
key的頭部。如果 key 不存在,那么在進行 push 操作前會創(chuàng)建一個空列表。如果 key 對應(yīng)的值不是 list 類型,那么會返回一個錯誤??梢允褂靡粋€命令把多個元素 push 進入列表。LPUSH?key?value?[value?...]RPUSH
Rpush 將向存儲在 key 中的列表的尾部插入所有指定的值。如果 key 不存在,那么會創(chuàng)建一個空的列表然后再進行 push 操作。當 key 保存的不是列表,那么會返回一個錯誤。
RPUSH?key?value?[value?...]LRANGE
Lrange將返回列表中指定區(qū)間內(nèi)的元素(閉區(qū)間),區(qū)間以偏移量 START 和 END 指定。其中 0 表示列表的第一個元素, 1 表示列表的第二個元素,以此類推。你也可以使用負數(shù)下標,以 -1 表示列表的最后一個元素, -2 表示列表的倒數(shù)第二個元素,以此類推。如果start大于最大小標,那么叫返回空列表。
LRANGE?key?start?stopLINDEX
Lindex 將返回列表 key 里索引 index 位置存儲的元素。index 下標是從 0 開始索引的,所以 0 是表示第一個元素, 1 表示第二個元素,并以此類推。負數(shù)索引用于指定從列表尾部開始索引的元素,在這種方法下,-1 表示最后一個元素,-2 表示倒數(shù)第二個元素,并以此往前推。當 key 值不是列表的時候,會返回錯誤。
LINDEX?key?indexLLEN
Llen 將用于返回存儲在
key中的列表長度。如果key不存在,則key被解釋為一個空列表,返回0。如果key不是列表類型,返回一個錯誤。LLEN?key
常用命令
LREM
Lrem將用于從列表 key 中刪除前 count 個值等于
element的元素。這個 count 參數(shù)通過下面幾種方式影響這個操作,如果count > 0, 從頭到尾刪除值為 value 的元素;如果count < 0,將從尾到頭刪除值為 value 的元素;如果 count = 0 將移除所有值為 value 的元素LREM?key?count?valueLSET
Lset 將用于設(shè)置列表 key 中 index 位置的元素值為
element。LSET?key?index?valueLINSERT
Linsert 將用于把
element插入到列表key的前面或后面。當key不存在時,這個list會被看作是空list,什么都不執(zhí)行;當key存在,值不是列表類型時,返回錯誤。LINSERT?key?BEFORE|AFTER?pivot?value
測試上面命令:
127.0.0.1:6379>?RPUSH?myarrs?1?1?1?1?2?2???#??從list的右邊開始往myarrs里面添加值
(integer)?6
127.0.0.1:6379>?LRANGE?myarrs?0?-1???????#?返回myarrs的List中所有值
1)?"1"
2)?"1"
3)?"1"
4)?"1"
5)?"2"
6)?"2"
127.0.0.1:6379>?LPUSH?myarrs?0?0?-1???#?從list的左邊開始往myarrs里面添加值
(integer)?9
127.0.0.1:6379>?LRANGE?myarrs?0?-1
1)?"-1"
2)?"0"
3)?"0"
4)?"1"
5)?"1"
6)?"1"
7)?"1"
8)?"2"
9)?"2"
127.0.0.1:6379>?LINDEX?myarrs?-2????#?根據(jù)索引返回List中的值
"2"
127.0.0.1:6379>?LLEN?myarrs?????????#?返回List中元素個數(shù)
(integer)?9
127.0.0.1:6379>?LREM?myarrs?2?1?????#?刪除myarrs中的1??count為2??所以從頭往尾刪除兩個1
(integer)?2
127.0.0.1:6379>?LRANGE?myarrs?0?-1
1)?"-1"
2)?"0"
3)?"0"
4)?"1"
5)?"1"
6)?"2"
7)?"2"
127.0.0.1:6379>?LREM?myarrs?-1?1????#?刪除myarrs中的1??count為-1??所以從尾往頭刪除1個1
(integer)?1
127.0.0.1:6379>?LRANGE?myarrs?0?-1??
1)?"-1"
2)?"0"
3)?"0"
4)?"1"
5)?"2"
6)?"2"
127.0.0.1:6379>?LREM?myarrs?0?2???#?刪除myarrs中的2??count為0??刪除所有等于2的元素
(integer)?2
127.0.0.1:6379>?LRANGE?myarrs?0?-1
1)?"-1"
2)?"0"
3)?"0"
4)?"1"
127.0.0.1:6379>?LSET?myarrs?2?5????#?根據(jù)索引設(shè)置myarrs的值,將索引為2?的位置賦值為5
OK
127.0.0.1:6379>?LRANGE?myarrs?0?-1??
1)?"-1"
2)?"0"
3)?"5"
4)?"1"
127.0.0.1:6379>?LINSERT?myarrs?before?5?4??#?在第一個值為5的位置的前面插入一個4
(integer)?5
127.0.0.1:6379>?LRANGE?myarrs?0?-1
1)?"-1"
2)?"0"
3)?"4"
4)?"5"
5)?"1"
5、哈希類型—hash命令:
hash類似于java中的HashMap,在Reids中做了更多的優(yōu)化。此外hash是一個sytring類型的field和value的映射表,特別適合用于存儲對象。例如我們可以借用hash數(shù)據(jù)結(jié)構(gòu)來存儲用戶信息,商品信息等。
基本命令
HSET
Hset 命令用于為存儲在
key中的哈希表的field字段賦值value。如果哈希表不存在,一個新的哈希表被創(chuàng)建并進行 HSET 操作。如果字段(field)已經(jīng)存在于哈希表中,舊值將被覆蓋。HSET?key?field?valueHGET
Hget 命令用于返回哈希表中指定字段
field的值。如果給定的字段或 key 不存在時,返回 nil 。HGET?key?fieldHMSET
Hmset 命令用于同時將多個 field-value (字段-值)對設(shè)置到哈希表中。此命令會覆蓋哈希表中已存在的字段,如果哈希表不存在,會創(chuàng)建一個空哈希表,并執(zhí)行 HMSET 操作。
HMSET?key?field?value?[field?value?...]HGETALL
Hgetall 命令用于返回存儲在
key中的哈希表中所有的域和值。返回值以列表形式返回哈希表的字段及字段值,若 key 不存在,返回空列表。HGETALL?keyHDEL
Hdel 命令用于刪除哈希表 key 中的一個或多個指定域,不存在的域?qū)⒈缓雎浴H绻?
key不存在,會被當作空哈希表處理并返回0。HDEL?key?field?[field?...]
常用命令
HEXISTS
Hexists 命令用于查看哈希表的指定字段
field是否存在。如果表含有給定字段field會返回1,否則返回0。HEXISTS?key?fieldHKEYS
Hkeys返回存儲在
key中哈希表的所有域。當 key 不存在時,返回空表。HKEYS?keyHVALS
Hvals 命令返回哈希表所有域(field)的值。當 key 不存在時,返回空表。
HVALS?key
測試以上命令
127.0.0.1:6379>?HSET?userinfo?name?jiangyou?????#??創(chuàng)建新的hash表,并存入對象userinfo的name屬性
(integer)?1?????????????????????????????????????#??返回賦值成功域的個數(shù)
127.0.0.1:6379>?HSET?userinfo?age?26?home?liaoming?school?neu????#??設(shè)置userinfo對象的多個域的值
(integer)?3?????????????????????????????????????#??返回賦值成功域的個數(shù)
127.0.0.1:6379>?HKEYS?userinfo??????????????????#??查看userinfo的所有域的名
1)?"name"
2)?"age"
3)?"home"
4)?"school"
127.0.0.1:6379>?HKEYS?users?????????????????????#??當key不存在時,返回空
(empty?list?or?set)
127.0.0.1:6379>?HVALS?userinfo??????????????????#??返回key值的所有域的值
1)?"jiangyou"
2)?"26"
3)?"liaoming"
4)?"neu"
127.0.0.1:6379>?HEXISTS?userinfo?name???????????#??查看哈希表的指定字段`name`?該字段存在,返回1
(integer)?1
127.0.0.1:6379>?HEXISTS?userinfo?addr???????????#??查看哈希表的指定字段`addr`?該字段存在,返回0
(integer)?0
127.0.0.1:6379>?HGETALL?userinfo????????????????#??查看哈希表中存儲在?`key`?中的所有的域和值
1)?"name"
2)?"jiangyou"
3)?"age"
4)?"26"
5)?"home"
6)?"liaoming"
7)?"school"
8)?"neu"
127.0.0.1:6379> HGETALL users ??????????????????#??`key`?不存在,會被當作空哈希表處理并返回。
(empty?list?or?set)
127.0.0.1:6379> HDEL userinfo school home ??????#???刪除哈希表 key 中的一個或多個指定域,返回的為成功刪除的域的個數(shù)。
(integer)?2
127.0.0.1:6379>?HGETALL?userinfo
1)?"name"
2)?"jiangyou"
3)?"age"
4)?"26"
6、集合類型—set命令:
基本命令
SADD
Sadd 將命令將一個或多個成員元素加入到集合中,已經(jīng)存在于集合的成員元素將被忽略。假如集合 key 不存在,則創(chuàng)建一個只包含被添加的元素作為成員的集合。當集合 key 不是集合類型時,返回一個錯誤。
?SADD?key?member?[member?...]SMEMBERS
Smembers 將返回存儲在
key中的集合的所有的成員。不存在的集合被視為空集合。?SMEMBERS?key??SISMEMBER
Sismember 將用于判斷元素
member是否集合key的成員。如果成員元素是集合的成員,返回 1 ;如果成員元素不是集合的成員,或key不存在,返回0。?SISMEMBER?key?memberSCARD
Scard 將返回集合中元素的數(shù)量。
?SCARD?key?SREM
Srem將在集合中刪除指定的元素。如果指定的元素不是集合成員則被忽略。如果集合
key不存在則被視為一個空的集合,該命令返回0。如果key的類型不是一個集合,則返回錯誤。?SCARD?key?member?[member?...]
常用命令
SRANDMEMBER
Srandmember 將僅使用
key參數(shù),那么隨機返回集合key中的一個隨機元素。如果count是整數(shù)且小于元素的個數(shù),返回含有 count 個不同的元素的數(shù)組,如果count是個整數(shù)且大于集合中元素的個數(shù)時,返回整個集合的所有元素,當count是負數(shù),則會返回一個包含count的絕對值的個數(shù)元素的數(shù)組,如果count的絕對值大于元素的個數(shù),則返回的結(jié)果集里會出現(xiàn)一個元素出現(xiàn)多次的情況。?SRANDMEMBER?key?[count]SPOP
Spop 將從集合
key中刪除并返回一個或多個隨機元素。這個命令和 SRANDMEMBER相似, SRANDMEMBER 只返回隨機成員但是不刪除這些返回的成員。?SRANDMEMBER?key?[count]
測試以上命令
127.0.0.1:6379>?SADD?name?zhangsan?lisi?wangwu???#??賦值key為name的set集合,返回賦值成功的個數(shù)
(integer)?3
127.0.0.1:6379> SMEMBERS name ???????????????????#??查看存儲在name中的集合的所有的成員。
1)?"zhangsan"
2)?"lisi"
3)?"wangwu"
127.0.0.1:6379>?SISMEMBER?name?zhangsan??????????#??判斷元素?zhangsan?是否集合?name?的成員,如果是??返回1
(integer)?1
127.0.0.1:6379>?SISMEMBER?name?xuliu?????????????#??判斷元素?xuliu?是否集合?name?的成員,如果不是??返回0
(integer)?0
127.0.0.1:6379>?SCARD?name
(integer)?3
127.0.0.1:6379> SREM name zhangsan xuliu ??????#??刪除 name 的成員,如果存在直接刪除,否則忽略。返回刪除成功的元素個數(shù)
(integer)?1
127.0.0.1:6379>?SMEMBERS?name
1)?"lisi"
2)?"wangwu"
127.0.0.1:6379>?SRANDMEMBER?name?5??#?隨機返回集合name中的一個隨機元素,count為5?大于集合個數(shù),返回整個集合元素?
1)?"lisi"
2)?"wangwu"
127.0.0.1:6379>?SRANDMEMBER?name?1??#?隨機返回集合name中的一個隨機元素,count為1?隨機返回集合中任意一個元素
1)?"wangwu"
127.0.0.1:6379>?SRANDMEMBER?name?-5??#?隨機返回集合name中的一個隨機元素,count為-5?返回的結(jié)果集里會出現(xiàn)一個元素出現(xiàn)多次
1)?"wangwu"
2)?"lisi"
3)?"lisi"
4)?"lisi"
5)?"wangwu"
127.0.0.1:6379>?SPOP?name?0??#?隨機刪除并返回集合name中的一個或多個隨機元素,count為0?返回的結(jié)果集里不會出現(xiàn)任何元素
(empty?array)
127.0.0.1:6379>?SPOP?name?1??#?隨機刪除并返回集合name中的一個或多個隨機元素,count為1?返回的結(jié)果集里會出現(xiàn)一個元素出現(xiàn)多次
1)?"lisi"
127.0.0.1:6379> SPOP name -5 #?隨機刪除并返回集合name中的一個或多個隨機元素,count 不能為負數(shù)。
(error)?ERR?value?is?out?of?range,?must?be?positive
7、有序集合類型—sortedset命令:
基本命令
ZADD
Zadd 將一個或多個
member元素及其score值加入到有序集key當中。如果某個member已經(jīng)是有序集的成員,那么更新這個member的score值,并通過重新插入這個member元素,來保證該member在正確的位置上。如果有序集合key不存在,則創(chuàng)建一個空的有序集并執(zhí)行 ZADD操作。當key存在但不是有序集類型時,返回一個錯誤。score值可以是整數(shù)值或雙精度浮點數(shù),score可為正也可以為負。ZADD?key?[NX|XX]?[CH]?[INCR]?score?member?[score?member?...]舉例子:
XX: 僅更新存在的成員,不添加新成員。 NX: 不更新存在的成員。只添加新成員。 LT: 更新新的分值比當前分值小的成員,不存在則新增。 GT: 更新新的分值比當前分值大的成員,不存在則新增。 CH: 返回變更成員的數(shù)量。變更的成員是指 新增成員 和 score值更新的成員,命令指明的和之前score值相同的成員不計在內(nèi)。注意: 在通常情況下,ZADD返回值只計算新添加成員的數(shù)量。 INCR: ZADD 使用該參數(shù)與 ZINCRBY 功能一樣。一次只能操作一個score-element對。 ZRANG
Zrange將返回有序集中,指定區(qū)間內(nèi)(閉區(qū)間)的成員,其中成員的按分數(shù)值遞增(從小到大)來排序,具有相同分數(shù)值的成員按字典序(lexicographical order )來排列。如果你需要成員按值遞減(從大到小)來排列,可以使用
ZREVRANGE命令。下標參數(shù)start和stop都以0為底,也就是說,以0表示有序集第一個成員,以1表示有序集第二個成員,以此類推。其中 start和stop參數(shù)的細節(jié)同ZRANG命令。ZRANGE?key?start?stop?[WITHSCORES]ZREVRANGE
Zervrange 將返回有序集
key中,指定區(qū)間內(nèi)的成員。其中成員的位置按score值遞減(從高到低)來排列。具有相同score值的成員按字典序的反序排列。除了成員排序相反外,ZREVRANGE命令的其他方面和ZRANGE命令一樣。ZREVRANGE?key?start?stop?[WITHSCORES]ZREM
Zrem 將從有序集合
key中刪除指定的成員member。如果member不存在則被忽略。當key存在,但是不是有序集合類型時,返回類型錯誤。返回的是從有序集合中刪除的成員個數(shù),不包括不存在的成員。ZREM?key?member?[member?...]ZCARD
Zcard 將返回有序集的成員個數(shù)。當
key不存在時,返回0。ZCARD?key
常用命令
ZRANGEBYSCORE
該指令將返回有序集
key中,所有score值介于min和max之間(包括等于min或max)的成員。有序集成員按score值遞增(從小到大)次序排列。具有相同score值的成員按字典序來排列(該屬性是有序集提供的,不需要額外的計算)??蛇x的LIMIT參數(shù)指定返回結(jié)果的數(shù)量及區(qū)間(就像SQL中的SELECT LIMIT offset, count),注意當offset很大時,定位offset的操作可能需要遍歷整個有序集,此過程最壞復(fù)雜度為 O(N) 時間。可選的WITHSCORES參數(shù)決定結(jié)果集是單單返回有序集的成員,還是將有序集成員及其score值一起返回。ZRANGEBYSCORE?key?min?max?[WITHSCORES]?[LIMIT?offset?count]ZREVRANGEBYSCORE
該指令將返回有序集合中指定分數(shù)區(qū)間的成員列表。有序集成員按分數(shù)值遞增(從小到大)次序排列。具有相同分數(shù)值的成員按字典序來排列(該屬性是有序集提供的,不需要額外的計算)。默認情況下,區(qū)間的取值使用閉區(qū)間 (小于等于或大于等于),你也可以通過給參數(shù)前增加 ( 符號來使用可選的開區(qū)間 (小于或大于)。可選的LIMIT參數(shù)指定返回結(jié)果的數(shù)量及區(qū)間(類似SQL中SELECT LIMIT offset, count)。注意,如果offset太大,定位offset就可能遍歷整個有序集合,這會增加O(N)的復(fù)雜度??蛇x參數(shù)WITHSCORES會返回元素和其分數(shù),而不只是元素。
ZREVRANGEBYSCORE??key?min?max?[WITHSCORES]?[LIMIT?offset?count]ZCOUNT
Zcount 將返回有序集
key中,score值在min和max之間(默認包括score值等于min或max)的成員的數(shù)量。ZCOUNT?key?min?max
Python調(diào)用Redis
在Python中,目前可以通過一個redis模塊來實現(xiàn)操控Redis,下面我們簡單的介紹一下關(guān)于使用redis模塊。
安裝Redis模塊
如果是在Windows 系統(tǒng),安裝 redis 模塊可以使用以下命令:
python?-m?pip?install?redis
如果是 Linux 系統(tǒng),需要執(zhí)行以下命令來安裝:
sudo?pip3?install?redis
如果是使用Anaconda管理環(huán)境,也可以使用以下命令安裝:
conda?install?redis
Python連接Redis
Redis模塊提供了兩種連接的模式:直連模式和連接詞模式。
直連模式
直連模式的方式簡單方便,適合少量長期連接的場景。其中host參數(shù)是ip地址,如果Redis服務(wù)存在于本地,可以使用127.0.0.1,或者換成Redis服務(wù)所在的ip地址。db表示當前選擇的庫,其參數(shù)值可以是 0-15;如果設(shè)置連接數(shù)據(jù)庫的密碼,那么就需要使用password進行驗證。
import?redis
r?=?redis.Redis(host='127.0.0.1',port=6379,db=0,password='')
r.set('name':'jiangyou')
print(r.get('name'))
連接池模式
連接池模式是使用 connection pool(連接池)來管理 redis server 的所有連接,每個Redis實例會維護自己的連接池來管理管理對一個 redis server 所有的連接,避免每次建立,釋放連接的開銷。
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,?max_connections=10)
r1?=?redis.Redis(connection_pool=pool)???#??第一個客戶端訪問
r2?=?redis.Redis(connection_pool=pool)???#??第二個客戶端訪問
上面的參數(shù),decode_responses=True 可以使得redis取出的結(jié)果改成字符串,其默認的是字節(jié), max_connections參數(shù)可以設(shè)置最大連接數(shù)量,這樣當有新的客戶端請求連接時,只需要去連接池獲取即可,這樣就可以把一個連接共享給多個客服端,減少每次連接所消耗的時間以及資源。
基本操作
在Redis模塊中,提供了Redis和StrictRedis來支持Redis訪問和操作。其中 StrictRedis 使用python基于Redis協(xié)議實現(xiàn)了所有官方的Redis操作命令,也就是說其實對于python操作redis的API接口和上面提到的Redis官方接口一樣。因此下面我們就簡單介紹一些常用的方法。
String操作
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
r.set('name','jiang')
r.append("name","you")?#?在redis?name對應(yīng)的值后面追加內(nèi)容
r.mset({'age':'26','home':'liaoning'})
print(r.mget('name','age','home'))
print("name 長度:%d"%r.strlen('name'))???#查看ame對應(yīng)值的長度
r.incrby('age',5)???#數(shù)值操作??將age對應(yīng)的值?加5
print(r.get('age'))
r.decrby('age',5)???#數(shù)值操作??將age對應(yīng)的值?減5
print(r.get('age'))
r.incrbyfloat('age',5.2)??#將age對應(yīng)的值?加5.2
print(r.get('age'))
r.incrbyfloat('age',-10.5)??#將age對應(yīng)的值?減10.5
print(r.get('age'))
r.setrange('name',5,'hahaha')??#?修改字符串內(nèi)容,從指定字符串索引開始向后替換。
print(r.getrange('name',0,6))???#??獲取子序列(根據(jù)字節(jié)獲取,非字符),閉區(qū)間
r.delete('name')??#刪除key運行結(jié)果
['jiangyou',?'26',?'liaoning']
name 長度:8
31
26
31.2
20.7
jianghaHash操作
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
r.hset('user1','name','zhangsan')???# user1對應(yīng)的hash中設(shè)置一個鍵值對(不存在,則創(chuàng)建;否則,修改)
r.hset('user1','age','22')??????????# user1對應(yīng)的hash中設(shè)置一個鍵值對(不存在,則創(chuàng)建;否則,修改)
r.hincrbyfloat('user1','age',0.5)???#?自增user1對應(yīng)的hash中的指定key的值,不存在則創(chuàng)建key=amount
print(r.hmget('user1','name','age'))??#?在user1對應(yīng)的hash中獲取多個key的值
#?一次性設(shè)置多個field和value
user_dict?=?{
??'password':'123',
??'gender':'M',
??'home':'遼寧'
}
r.hmset('user1',user_dict)????????#??在user1對應(yīng)的hash中批量設(shè)置鍵值對?
print("user1中存在鍵值對的個數(shù):%d "%r.hlen('user1'))?#??獲取所有數(shù)據(jù),字典類型
print("user1中存在鍵值對的具體信息:%s"%r.hgetall('user1'))?#??獲取所有數(shù)據(jù),字典類型
print(r.hkeys("user1"))??#?獲取所有fields字段
print(r.hvals("user1"))??#?獲取所有fields字段的values值
if?r.hexists("user1","home"):????????????#??檢查user1對應(yīng)的hash是否存在當前傳入的home
????r.hdel("user1",'home')???????????????#??將user1對應(yīng)的hash中指定key的鍵值對刪除
????print("已刪除該鍵!??!")
else:
????print("不存在該鍵?。?!")運行結(jié)果
['zhangsan',?'22.5']
user1中存在鍵值對的個數(shù):5?
user1中存在鍵值對的具體信息:{'name':?'zhangsan',?'age':?'22.5',?'password':?'123',?'gender':?'M',?'home':?'遼寧'}
['name',?'age',?'password',?'gender',?'home']
['zhangsan',?'22.5',?'123',?'M',?'遼寧']
已刪除該鍵!!List操作
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
r.lpush('database','sql','mysql','redis')?????#???在database對應(yīng)的list中添加元素,每個新的元素都添加到列表的最左邊
print(r.lrange('database',0,-1))?
r.linsert('database','before','mysql','mongodb')???#???在database對應(yīng)的列表的某一個值前或后插入一個新值,其含義為在第三個參數(shù)的前(before)或后(after)?插入?yún)?shù)四
print(r.lrange('database',0,-1))????????#??在database對應(yīng)的列表分片獲取數(shù)據(jù)
print("database中元素個數(shù):%d"%r.llen('database'))??#??database對應(yīng)的list元素的個數(shù)
print("database中第2個元素:%s"%r.lindex('database',2))??#在database對應(yīng)的列表中根據(jù)索引獲取列表元素
r.lset('database',?0,?'redisdb')???#??對database對應(yīng)的list中的某一個索引位置重新賦值?????
print(r.lrange('database',0,-1))???
print(r.rpop('database'))?????#??在database對應(yīng)的列表的右側(cè)獲取第一個元素并在列表中移除,返回值則是第一個元素
print(r.ltrim('database',0,1))???#?在database對應(yīng)的列表中移除沒有在start-end索引之間的值
while?True:
??result?=?r.brpop('database',1)?????#?從一個列表的右側(cè)移除一個元素并將其添加到另一個列表的左側(cè)??[如果列表中為空時,則返回None]
??if?result:
??????print(result)
??else:
??????break
r.delete('database')運行結(jié)果
['redis',?'mysql',?'sql']
['redis',?'mongodb',?'mysql',?'sql']
database中元素個數(shù):4
database中第2個元素:mysql
['redisdb',?'mongodb',?'mysql',?'sql']
sql
True
('database',?'mongodb')
('database',?'redisdb')Set操作
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
r.sadd("name","zhangsan")????????#??給name對應(yīng)的集合中添加元素
r.sadd("name","zhangsan","lisi","wangwu")
print(r.smembers('name'))?????????#??獲取name對應(yīng)的集合的所有成員
print(r.scard("name")?)???????????????#??獲取name對應(yīng)的集合中的元素個數(shù)
print(r.sismember('name','zhangsan'))???#??檢查value是否是name對應(yīng)的集合內(nèi)的元素,返回值為True或False
print(r.spop('name'))?????#??隨機刪除并返回指定集合的一個元素
print(r.smembers('name'))?
#?srem(name,?value)
print(r.srem("name",?"zhangsan"))??????????#??刪除集合中的某個元素
print(r.smembers('name'))?
????????????
r.sadd("name","a","b")
r.sadd("name1","b","c")
r.sadd("name2","b","c","d")
print(r.sinter("name","name1","name2"))??#??獲取多個name對應(yīng)集合的交集
print(r.sunion("name","name1","name2"))???#??獲取多個name對應(yīng)的集合的并集
print(r.sdiff("name","name1","name2"))???#??在第一個name對應(yīng)的集合中且不在其他name對應(yīng)的集合的元素集合
r.flushall()運行結(jié)果
{'zhangsan',?'lisi',?'wangwu'}
3
True
lisi
{'zhangsan',?'wangwu'}
1
{'wangwu'}
{'b'}
{'d',?'c',?'b',?'wangwu',?'a'}
{'wangwu',?'a'}SortedSet操作
import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
mapping?=?{
????'zhangsan':85,
????'lisi':92,?
????'wangwu':76
}
r.zadd('C++',mapping,nx=True)???????#??在C++對應(yīng)的有序集合中添加元素
print(r.zrange('C++',0,-1,withscores=True))???#??獲取C++對應(yīng)的有序集合的所有元素
print(r.zcard("C++"))???????????????#?獲取C++對應(yīng)的有序集合元素的數(shù)量
print(r.zcount('C++',min=0,max=90))?#?獲取C++對應(yīng)的有序集合中分數(shù)?在?[min,max]?之間的個數(shù)
r.zincrby(name='C++',value='lisi',amount=3)???#?增加C++對應(yīng)的有序集合的lisi對應(yīng)的分數(shù)
print(r.zrange('C++',0,-1,desc=False,withscores=True))??#?按照索引范圍獲取C++對應(yīng)的有序集合的元素,排序規(guī)則,默認按照分數(shù)從小到大排序
print(r.zrevrange('C++',0,-1,withscores=True))??#?按照索引范圍獲取C++對應(yīng)的有序集合的元素,排序規(guī)則,默認按照分數(shù)從大到小排序
print(r.zrangebyscore('C++',70,90))??#?按照分數(shù)范圍獲取C++對應(yīng)的有序集合的元素,排序規(guī)則,默認按照分數(shù)從小到大排序
print(r.zrevrangebyscore('C++',90,70))??#?按照分數(shù)范圍獲取C++對應(yīng)的有序集合的元素,排序規(guī)則,默認按照分數(shù)從大到小排序
print(r.zrank('C++','lisi'))???#? Zrank 返回有序集中指定成員的排名,有序集成員按分數(shù)值遞增(從小到大)順序排列。
print(r.zrevrank('C++','lisi'))???#? Zrevrank 返回有序集中指定成員的排名,有序集成員按分數(shù)值遞增(從大到小)順序排列。
mapping?=?{
????'xuliu':74,
????'lisi':82,?
????'wangwu':87
}
r.zadd('python',mapping,nx=True)
r.zinterstore('sum_score_i',['C++','python'],aggregate='sum')???#?獲取兩個有序集合的交集,如果遇到相同值不同分數(shù),則按照aggregate進行操作
print(r.zrange('sum_score_i',0,-1,withscores=True))
print(r.zunionstore('sum_score_u',['C++','python'],'min'))??#?獲取兩個有序集合的并集,如果遇到相同值不同分數(shù),則按照aggregate進行操作
print(r.zrange('sum_score_u',0,-1,withscores=True))
r.zrem('C++',?'zhangsan')?????????????????#??刪除C++對應(yīng)的有序集合中值是zhangsan的成員
print(r.zrange('C++',0,-1,withscores=True))
r.zremrangebyscore('C++',?min=80,?max=100)??????#?刪除C++對應(yīng)的有序集合中值是zhangsan的成員
print(r.zrange('C++',0,-1,withscores=True))
r.zremrangebyrank('python',?min=1,?max=3)???????#?根據(jù)排行范圍刪除
print(r.zrange('python',0,-1,withscores=True))運行結(jié)果
[('wangwu',?76.0),?('zhangsan',?85.0),?('lisi',?92.0)]
3
2
[('wangwu',?76.0),?('zhangsan',?85.0),?('lisi',?95.0)]
[('lisi',?95.0),?('zhangsan',?85.0),?('wangwu',?76.0)]
['wangwu',?'zhangsan']
['zhangsan',?'wangwu']
2
0
[('wangwu',?163.0),?('lisi',?177.0)]
4
[('xuliu',?74.0),?('wangwu',?76.0),?('lisi',?82.0),?('zhangsan',?85.0)]
[('wangwu',?76.0),?('lisi',?95.0)]
[('wangwu',?76.0)]
[('xuliu',?74.0)]管道操作
Redis 模塊默認在執(zhí)行每次請求都會向連接池請求創(chuàng)建連接和斷開申請操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現(xiàn)一次請求指定多個命令,并且默認情況下一次pipline 是原子性操作(即為一次操作)。
?import?redis
pool?=?redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,decode_responses=True,max_connections=10)
r?=?redis.StrictRedis(connection_pool=pool)
pipe?=?r.pipeline(transaction=True)
pipe.set('name',?'jiangyou')
pipe.set('age',?'age')
pipe.execute()
print(r.mget("name","age"))運行結(jié)果
['jiangyou',?'age']
--end-- 掃碼即可加我微信
學習交流
老表朋友圈經(jīng)常有贈書/紅包福利活動
