Python 資料庫騷操作 — Redis

zone_5808fa1d0d5f6發表於2019-02-16

目錄

  • 前言
  • Redis GUI 工具
  • Redis 遇上 Docker
  • Redis string
  • Redis hash
  • Redis list
  • Redis set
  • Redis zset
  • 後記

前言

前面一篇文章介紹了 MongoDB 的庫,我把 MySQL 放在了最後面,這篇文章繼續介紹 Redis 的操作。Redis支援五種資料型別:string(字串),hash(雜湊),list(列表),set(集合)及zset(sorted set:有序集合)。接下來會簡單介紹一下,Python 與 Redis 的化學反應。

Python 資料庫騷操作 — Redis

Redis GUI 工具

首先介紹一款 Redis 的 GUI 工具 Medis,初學 Redis 用這個來檢視資料真的很爽。可以即時看到資料的增刪改查,不用操作命令列來檢視。

主介面
操作介面圖

Redis 遇上 Docker

關注我的人都知道,我的簡介上面寫著我的公眾號會涉及 Docker 相關的知識,但最近的文章也沒怎麼涉及,所以後面的文章中,能跟 Docker 扯上關係的,我都會粗略地說一下。這裡主要貼一貼配置程式碼,docker-compose 程式碼如下。

version: `3`
services:
  redis_container:
    image: redis
    command: redis-server --requirepass yourpassword # 配置 Redis 密碼
    ports:
      - "6378:6379" # 對映埠
    volumes:
      - /your/path/data:/data 
複製程式碼

啟動命令

docker-compose up -d
複製程式碼

Redis string

install

pip install redis
複製程式碼

連線

# 普通連線
r = redis.StrictRedis(host=`localhost`, port=6379, db=0)
r = redis.StrictRedis(host=`localhost`, port=6379, password="your password", db=0)

# 連線池
"""
redis-py 使用 connection pool 來管理對一個 redis server 的所有連線,避免每次建立、釋放連線的開銷。預設,每個Redis例項都會維護一個自己的連線池,這樣就可以實現多個 Redis 例項共享一個連線池
"""
# host 是 redis 服務 ip,預設埠是6379
pool = redis.ConnectionPool(host=`localhost`, port=6379,decode_responses=True)  
r = redis.Redis(connection_pool=pool)
複製程式碼

增加

set(name, value, ex=None, px=None, nx=False, xx=False)

在Redis中設定值,預設,不存在則建立,存在則修改
引數:
ex,過期時間(秒)
px,過期時間(毫秒)
nx,如果設定為True,則只有name不存在時,當前set操作才執行
xx,如果設定為True,則只有name存在時,當前set操作才執行
複製程式碼
# 設定過期時間為 1 秒
r.set(`foo`, `zone`, ex=1)
# 效果同上
r.setex(`foo`, `zone`, 1)
# 效果同上
r.psetex(`foo`, 1000, `zone`)

print(r.get(`foo`))

# 休眠兩秒後,再列印輸出
time.sleep(2)
print(r.get(`foo`))
複製程式碼

查詢

get(key)
普通查詢
複製程式碼
print(r.get(`foo`))
複製程式碼
mget(keys, *args)
批量查詢
複製程式碼
# 批量獲取
print(r.mget("k1", "k2"))  # 一次取出多個鍵對應的值
print(r.mget("k1"))
複製程式碼

獲取子序列

getrange(key, start, end)
獲取子序列(根據位元組獲取,非字元)
引數:
name,Redis 的 name
start,起始位置(位元組)
end,結束位置(位元組)
複製程式碼
# 一個漢字3個位元組 1個字母一個位元組
r.set("name", "zonezone")
print(r.getrange(`name`, 0, 3))
# 獲取所有位元組
print(r.getrange(`name`, 0, -1))

複製程式碼
獲取結果

修改

原始值 zonezone ,修改後變為 zone is a boy

setrange(name, offset, value)
修改字串內容,從指定字串索引開始向後替換(新值太長時,則向後新增)
引數:
offset,字串的索引,位元組(一個漢字三個位元組)
value,要設定的值
複製程式碼
r.set("name", "zonezone")
r.setrange("name", 4, " is a boy")
print(r.get("name")) 
複製程式碼
修字串成功

返回相應 key 的字串長度

r.set("name", "zonezone")
print(r.strlen("name"))
複製程式碼

自增 name 對應的值(int)

incr(self, name, amount=1)
自增 name對應的值,當name不存在時,則建立name=amount,否則,則自增。
引數:
name,Redis的name
amount,自增數(必須是整數)
複製程式碼
r.set("age", 123)
print(r.get("age"))
r.incr("age", amount=1)
print(r.get("age"))
複製程式碼
自增成功

自增 name 對應的值(float)

incrbyfloat(self, name, amount=1.0)
自增 name對應的值,當name不存在時,則建立name=amount,否則,則自增。
引數:
name,Redis的name
amount,自增數(浮點型)
複製程式碼
r.set("age", 123.0)
print(r.get("age"))
r.incrbyfloat("age", amount=0.2)
print(r.get("age"))

複製程式碼
Python 資料庫騷操作 — Redis

自減 name 對應的值

r.set("age", 123)
r.decr("age", amount=1) # 遞減1
print(r.mget("foo1", "foo4"))
複製程式碼

追加內容

append(key, value)
在redis name對應的值後面追加內容
引數:
key, redis的name
value, 要追加的字串
複製程式碼
r.set("name", "關注 ")
print(r.get("name"))
r.append("name","公眾號【zone7】")
print(r.get("name"))
複製程式碼
Python 資料庫騷操作 — Redis

Redis hash

hash

hset(name, key, value)
name對應的hash中設定一個鍵值對(不存在,則建立;否則,修改)
引數:
name,redis的name
key,name對應的hash中的key
value,name對應的hash中的value
注:
hsetnx(name, key, value),當name對應的hash中不存在當前key時則建立(相當於新增)
複製程式碼
r.hset("hash1", "k1", "v1")
r.hset("hash1", "k2", "v2")
# 取hash中所有的key
print(r.hkeys("hash1")) 
# 單個取hash的key對應的值
print(r.hget("hash1", "k1"))    
# 多個取hash的key對應的值
print(r.hmget("hash1", "k1", "k2")) 
r.hsetnx("hash1", "k2", "v3")
print(r.hget("hash1", "k2"))
複製程式碼
Python 資料庫騷操作 — Redis

批量增加與批量獲取

# 批量增加
r.hmset("hash2", {"k1": "v1", "k2": "v2"})
# 批量獲取
print(r.hmget("hash2", "k1", "k2"))
複製程式碼
Python 資料庫騷操作 — Redis

去除所有 hash 鍵值對

print(r.hgetall("hash1"))
複製程式碼

獲取 hash長度

hlen(name)
獲取name對應的hash中鍵值對的個數
複製程式碼
print(r.hlen("hash1"))
複製程式碼

獲取所有的keys(類似字典的取所有keys)

hkeys(name)
獲取name對應的hash中所有的key的值
複製程式碼
print(r.hkeys("hash1"))
複製程式碼

獲取所有的value(類似字典的取所有value)

hvals(name)
獲取name對應的hash中所有的value的值
複製程式碼
print(r.hvals("hash1"))
複製程式碼

判斷成員是否存在(類似字典的in)

hexists(name, key)
檢查name對應的hash是否存在當前傳入的key
複製程式碼
print(r.hexists("hash1", "k1")) 
複製程式碼

刪除鍵值對

hdel(name,*keys)
將name對應的hash中指定key的鍵值對刪除
複製程式碼
r.hset("hash1", "name", "zone")
print(r.hget("hash1", "name"))
r.hdel("hash1", "name")
print(r.hget("hash1", "name"))
複製程式碼
Python 資料庫騷操作 — Redis

自增自減(int)

hincrby(name, key, amount=1)
自增name對應的hash中的指定key的值,不存在則建立key=amount
引數:
name,redis中的name
key, hash對應的key
amount,自增數(整數)
複製程式碼
r.hset("hash1", "age", 123)
r.hincrby("hash1", "age", amount=-1)
print(r.hget("hash1", "age"))
r.hincrby("hash1", "age", amount=1)  # 不存在的話,value預設就是1
print(r.hget("hash1", "age"))
複製程式碼
Python 資料庫騷操作 — Redis

自增自減(float)

hincrbyfloat(name, key, amount=1.0)
自增name對應的hash中的指定key的值,不存在則建立key=amount
引數:
name,redis中的name
key, hash對應的key
amount,自增數(浮點數)
自增name對應的hash中的指定key的值,不存在則建立key=amount
複製程式碼
r.hset("hash1", "age", 123.0)
r.hincrbyfloat("hash1", "age", amount=-0.3)
print(r.hget("hash1", "age"))
r.hincrbyfloat("hash1", "age", amount=0.5)  # 不存在的話,value預設就是1
print(r.hget("hash1", "age"))
複製程式碼

Redis list

增加(不存在會自動建立)

lpush(name,values)
在name對應的list中新增元素,每個新的元素都新增到列表的最左邊
rpush(name,values)
在name對應的list中新增元素,每個新的元素都新增到列表的最右邊
複製程式碼
r.lpush("left_list", 11, 22, 33)
print(r.lrange(`left_list`, 0, -1))

r.rpush("right_list", 11, 22, 33)
print(r.lrange("right_list", 0, 3))

print(r.llen("right_list"))  # 列表長度
複製程式碼
Python 資料庫騷操作 — Redis

新增(不存在不會自動建立)

lpushx(name,value)
在name對應的list中新增元素,只有name已經存在時,值新增到列表的最左邊。不存在時,不會自動建立。
複製程式碼
r.lpushx("left_list", 2222)
print(r.lrange(`left_list`, 0, -1))

r.rpushx("right_list", 1111)
print(r.lrange(`right_list`, 0, -1))
複製程式碼
有兩個 2222 是因為我手抖,多執行了一遍

新增

新增(固定索引號位置插入元素)
linsert(name, where, refvalue, value))
在name對應的列表的某一個值前或後插入一個新值
引數:
name,redis的name
where,BEFORE或AFTER
refvalue,標杆值,即:在它前後插入資料
value,要插入的資料
複製程式碼
# 往列表中左邊第一個出現的元素"11"前插入元素"00"
r.linsert("left_list", "before", "11", "00") 
print(r.lrange("left_list", 0, -1))
複製程式碼
Python 資料庫騷操作 — Redis

修改

修改(指定索引號進行修改)
r.lset(name, index, value)
對name對應的list中的某一個索引位置重新賦值
引數:
name,redis的name
index,list的索引位置
value,要設定的值
複製程式碼
r.lset("left_list", 0, "關注公眾號【zone7】")    # 把索引號是0的元素修改成 關注公眾號【zone7】
print(r.lrange("left_list", 0, -1))
複製程式碼
Python 資料庫騷操作 — Redis

刪除

刪除(指定值進行刪除)
r.lrem(name, value, num)
在name對應的list中刪除指定的值
引數:
name,redis的name
value,要刪除的值
num, num=0,刪除列表中所有的指定值;
num=2,從前到後,刪除2個; num=1,從前到後,刪除左邊第1個
num=-2,從後向前,刪除2個
複製程式碼
# 將列表中左邊第一次出現的"33"刪除
r.lrem("left_list", "33", 1)   
print(r.lrange("left_list", 0, -1))
複製程式碼
刪除 33

刪除並返回

lpop(name)
在 name 對應的列表的左邊獲取第一個元素並在列表中移除,返回值則是第一個元素
rpop(name)
在 name 對應的列表的右邊獲取第一個元素並在列表中移除,返回值則是第一個元素
複製程式碼
print(r.lpop("left_list"))
print(r.lrange("list2", 0, -1))
複製程式碼

Redis set

增加

sadd(name,values)
新增元素
複製程式碼
r.sadd("set1", 1, 2, 3, 4)
# 獲取集合長度
print(r.scard("set1"))  
# 獲取集合中所有元素
print(r.smembers("set1")) 
複製程式碼
Python 資料庫騷操作 — Redis

刪除

# 普通刪除
srem(name, values)
在name對應的集合中刪除某些值
複製程式碼
 # 從集合中刪除指定值 1
print(r.srem("set1", 1))  
print(r.smembers("set1"))
複製程式碼
刪除了值 1
# 隨機刪除並返回被刪除值
spop(name)
從集合移除一個成員,並將其返回,說明一下,集合是無序的,所有是隨機刪除的
複製程式碼
print(r.spop("set2"))   # 這個刪除的值是隨機刪除的,集合是無序的
print(r.smembers("set2"))
複製程式碼

查詢

# 普通獲取
smembers(name)
獲取name對應的集合的所有成員
複製程式碼
print(r.smembers("set1"))   # 獲取集合中所有的成員
複製程式碼
# 以元組形式獲取集合
sscan(name, cursor=0, match=None, count=None)
複製程式碼
print(r.sscan("set1"))
複製程式碼
# 以迭代器的方式獲取集合
sscan_iter(name, match=None, count=None)
同字串的操作,用於增量迭代分批獲取元素,避免記憶體消耗太大
複製程式碼
for i in r.sscan_iter("set1"):
    print(i)
複製程式碼

交集

sinter(keys, *args)
獲取多個 name 對應集合的交集
複製程式碼
r.sadd("set2", 1, 2, 3, 4)
r.sadd("set3", 3, 4, 5, 6)
print(r.sinter("set2", "set3"))
複製程式碼
交集為 3、4
sinterstore(dest, keys, *args)
獲取多個 name 對應集合的並集,再將並集加入到 dest(目標集合) 中
複製程式碼
r.sadd("set2", 1, 2, 3, 4)
r.sadd("set3", 3, 4, 5, 6)
print(r.sinterstore("set4", "set2", "set3"))
print(r.smembers("set4"))
複製程式碼
交集為 3、4

移動

smove(src, dst, value)
將某個成員從一個集合中移動到另外一個集合
複製程式碼
r.smove("set2", "set3", 3)
print(r.smembers("set2"))
print(r.smembers("set3"))
複製程式碼
將 set2 中的元素 3 移動至 set3

判斷集合中是否有某元素

sismember(name, value)
檢查value是否是name對應的集合的成員,結果為True和False
複製程式碼
print(r.sismember("set2", 3))
print(r.sismember("set3", 1))
複製程式碼

並集

sunion(keys, *args)
獲取多個name對應的集合的並集
複製程式碼
r.sadd("set2", 1, 2, 3, 4)
r.sadd("set3", 3, 4, 5, 6)
print(r.sunion("set2", "set3"))
複製程式碼
無序集
並集--並集存在一個新的集合
sunionstore(dest,keys, *args)
獲取多個name對應的集合的並集,並將結果儲存到dest對應的集合中
複製程式碼
r.sadd("set2", 1, 2, 3, 4)
r.sadd("set3", 3, 4, 5, 6)
print(r.sunionstore("set4", "set2", "set3")) # 取2個集合的並集
print(r.smembers("set4"))
複製程式碼
無序集

Redis zset

set 就是無序,不允許重複的列表

增加

zadd(name, *args, **kwargs)
在name對應的有序集合中新增元素
複製程式碼
r.zadd("zset1", n1=123, n2=234)
print(r.zrange("zset1", 0, -1))   # 獲取有序集合中所有元素
# 效果同上
r.zadd("zset1", `n1`, 123, `n2`, 234)
複製程式碼
Python 資料庫騷操作 — Redis

刪除

zrem(name, values)
刪除name對應的有序集合中值是values的成員
複製程式碼
# 刪除 n2
r.zrem("zset2", "n2")
print(r.zrange("zset2", 0, -1))
複製程式碼
n2 已被刪除
zremrangebyrank(name, min, max)
根據索引刪除
複製程式碼
# 根據索引刪除
r.zremrangebyrank("zset2", 0, 1)
print(r.zrange("zset2", 0, -1))
複製程式碼
刪除索引為 0、1 的值,即刪除 n3、n4

zscore(name, value)
獲取name對應有序集合中 value 對應的分數
複製程式碼
# 查詢 n5 的值
print(r.zscore("zset2", "n5"))
複製程式碼
Python 資料庫騷操作 — Redis

獲取 set 的長度

print(r.zcard("zset1")) 
複製程式碼

獲取有序集合的所有元素

r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
按照索引範圍獲取name對應的有序集合的元素
引數:
name,redis的name
start,有序集合索引起始位置(非分數)
end,有序集合索引結束位置(非分數)
desc,排序規則,預設按照分數從小到大排序
withscores,是否獲取元素的分數,預設只獲取元素的值
score_cast_func,對分數進行資料轉換的函式
複製程式碼

從大到小排序(同zrange,集合是從大到小排序的)

zrevrange(name, start, end, withscores=False, score_cast_func=float)

# 只獲取元素,不顯示分數
print(r.zrevrange("zset1", 0, -1))    
# 獲取有序集合中所有元素和分數,分數倒序
print(r.zrevrange("zset1", 0, -1, withscores=True))
複製程式碼
Python 資料庫騷操作 — Redis

統計範圍內元素個數

zcount(name, min, max)
獲取name對應的有序集合中分數 在 [min,max] 之間的個數
複製程式碼
for i in range(1, 30):
    key = `n` + str(i)
    r.zadd("zset2", key, i)
print(r.zrange("zset2", 0, -1, withscores=True))
print(r.zcount("zset2", 1, 9))
複製程式碼
太長了,我擷取了部分

自增

zincrby(name, value, amount)
自增name對應的有序集合的 name 對應的分數
複製程式碼
# 每次將n1的分數自增5
r.zincrby("zset2", "n2", amount=5)
print(r.zrange("zset2", 0, -1, withscores=True))
複製程式碼
n1 已增加 5

獲取值的索引號

zrank(name, value)
獲取某個值在 name對應的有序集合中的索引(從 0 開始)
複製程式碼
# 獲取 n2 的索引號
print(r.zrank("zset2", "n2"))
複製程式碼

後記

在微信公眾號後臺回覆「Redis」獲取原始碼。Redis 的騷操作就介紹到這裡,後面會繼續寫 MySQL 的騷操作。盡請期待。

本文首發於公眾號「zone7」,關注獲取最新推文!

image

相關文章