Background

最近因為工作的需要,需要一台cache server來優化一下performance。以前都是用 Memcache,這次想說來換一下好了換成 Redis 並記錄一下簡單的使用心得。 主要是使用 Python 來搭配 Redis

Redis 是一個 in-memory 的 key-value database,因此常常被用在需要快取(Cache)一些資料的場合,可以減輕許多後端資料庫的壓力。

Setting & Installation

$ mkdir redis
$ cd redis
$ virtualenv .venv
$ source .venv/bin/activate
$ pip3 install redis
$ touch run.py

Basic

在Redis的中設置值,默認,不存在則創建,存在則修改

參數:
當然,過期時間(秒)
像素,過期時間(毫秒)
NX,如果設置為真,則只有名稱不存在時,當前設定操作才執行
XX,如果設置為真,則只有名稱存在時,當前設定操作才執行

run.py

import redis
import sys
import os
import time

rds = redis.Redis(
    host="127.0.0.1",
    port=6379,
    password="",
)

def main():

    print("=== basic ===")
    rds.set("hello", "hello world")
    print(rds.get("hello"))

    rds.set("hello-3s", "hello world", ex=3)
    print("before sleep:", rds.get("hello-3s"))
    time.sleep(4)
    print("after sleep:", rds.get("hello-3s"))

    # nx,如果設置為True,則只有名稱不存在時,當前設置操作才執行(新建),與setnx相同
    rds.set("hello", "hello world-nx", nx=True)
    print(rds.get("hello"))
    rds.set("hello-nx", "hello world-nx", nx=True)
    print(rds.get("hello-nx"))

    # xx,如果設置為True,則只有名稱存在時,當前設置操作才執行(修改)
    rds.set("hello", "hello world-xx", xx=True)
    print(rds.get("hello"))
    rds.set("hello-xx", "hello world-xx", xx=True)
    print(rds.get("hello-xx"))


if __name__ == "__main__":
    main()
$ python3 run.py
=== basic ===
b'hello world'
before sleep: b'hello world'
after sleep: None
b'hello world'
b'hello world-nx'
b'hello world-xx'
None

Hash

run.py

def hash_feature():

    print("=== hash ===")
    rds.hset("user-1", "name", "Paul")
    rds.hset("user-1", "phone", "0933777222")
    rds.hset("user-1", "city", "Taipei")
    rds.hset("user-1", "email", "[email protected]")
    # 取hash中所有的key
    print(rds.hkeys("user-1"))
    # get a key value from hash
    print(rds.hget("user-1", "name"))
    # get mutiple key value from hash
    print(rds.hmget("user-1", "name", "city"))

    rds.hmset("user-2", {"name": "Taiker", "phone": "09112223333", "city": "Taipei", "email": "[email protected]"})
    print(rds.hkeys("user-2"))
    print(rds.hget("user-2", "name"))
    print(rds.hmget("user-2", "name", "city"))

    print(rds.hgetall("user-1"))  #return dict
    print(rds.hlen("user-1"))     #len of hash map
    print(rds.hkeys("user-1"))
    print(rds.hvals("user-1"))

    print(rds.hexists("user-1", "age"))   # False 不存在
    print(rds.hexists("user-1", "name"))  # True 存在


    rds.hdel("user-1", "email")    # delete a key from hash
    print(rds.hgetall("user-1"))

if __name__ == "__main__":
    main()
    hash_feature()
$ python3 run.py
...
...
=== hash ===
[b'name', b'phone', b'city', b'email']
b'Paul'
[b'Paul', b'Taipei']
[b'name', b'phone', b'city', b'email']
b'Taiker'
[b'Taiker', b'Taipei']
{b'name': b'Paul', b'phone': b'0933777222', b'city': b'Taipei', b'email': b'[email protected]'}
4
[b'name', b'phone', b'city', b'email']
[b'Paul', b'0933777222', b'Taipei', b'[email protected]']
False
True
{b'name': b'Paul', b'phone': b'0933777222', b'city': b'Taipei'}

Key

run.py

def key_feature():

    print("=== key ===")
    # 取出所有開頭字串為user的key值
    print(rds.keys("user*"))

    for i in rds.hscan_iter("user-1"):
        print(i)
        

if __name__ == "__main__":
    main()
    hash_feature()
    key_feature()
$ python3 run.py
...
...
=== key ===
[b'user-1', b'user-2']
(b'name', b'Paul')
(b'phone', b'0933777222')
(b'city', b'Taipei')

Set

run.py

def set_feature():

    print("=== set ===")
    rds.sadd("team-1", 1, 2, 3, 4)  # add value to set
    print(rds.scard("team-1"))      # return length of set
    print(rds.smembers("team-1"))   # get all members of set

    for i in rds.sscan_iter("team-1"):
        print(i)

    rds.sadd("team-2", 4, 5, 6)
    print(rds.sdiff("team-1", "team-2"))   # 在集合team-1但是不在集合team-2中
    print(rds.sdiff("team-2", "team-1"))   # 在集合team-2但是不在集合team-1中

    print(rds.sinter("team-1", "team-2")) # 取2個集合的交集
    print(rds.sunion("team-1", "team-2")) # 取2個集合的聯集

    rds.smove("team-1", "team-2", 2)
    print(rds.smembers("team-1"))
    print(rds.smembers("team-2"))

    print(rds.srem("team-2", 1))   # delete selected value from set, return True, False
    print(rds.smembers("team-2"))
    
if __name__ == "__main__":
    main()
    hash_feature()
    key_feature()
    set_feature()
$ python3 run.py
...
...
=== set ===
4
{b'4', b'3', b'2', b'1'}
b'1'
b'2'
b'3'
b'4'
{b'3', b'1'}
{b'6', b'5'}
{b'4', b'2'}
{b'3', b'5', b'2', b'1', b'4', b'6'}
{b'4', b'3', b'1'}
{b'6', b'4', b'5', b'2'}
0
{b'6', b'4', b'5', b'2'}

Sorted Set

run.py

def sorted_set_feature():

    print("=== Sorted Set ===")
    # ZADD name {key: value, ...}, redis3.0
    rds.zadd("rank", {"Tom": 100, "John": 80, "Claire": 70, "Mary": 50})

    print(rds.zcard("rank")) # get length of sorted set
    print(rds.zrange("rank", 0, -1))   # get all key from sorted set
    print(rds.zrange("rank", 0, -1, withscores=True))
    print(rds.zrange("rank", 0, -1, desc=True, withscores=True))
    print(rds.zrangebyscore("rank", 70, 90, withscores=True))

    #zrem(name, values)
    rds.zrem("rank", "Tom")   # delete Tom for sorted set
    print(rds.zrange("rank", 0, -1))

    rds.zremrangebyscore("rank", 70, 90)   # delete key from sorted set which score between 70-90
    print(rds.zrange("rank", 0, -1))
$ python3 run.py
...
...
=== Sorted Set ===
4
[b'Mary', b'Claire', b'John', b'Tom']
[(b'Mary', 50.0), (b'Claire', 70.0), (b'John', 80.0), (b'Tom', 100.0)]
[(b'Tom', 100.0), (b'John', 80.0), (b'Claire', 70.0), (b'Mary', 50.0)]
[(b'Claire', 70.0), (b'John', 80.0)]
[b'Mary', b'Claire', b'John']
[b'Mary']

Reference