官术网_书友最值得收藏!

Redis應(yīng)用實(shí)例

1.5 實(shí)現(xiàn)代碼:使用JSON/哈希鍵緩存多項(xiàng)數(shù)據(jù)

代碼清單1-2展示了使用JSON緩存多項(xiàng)數(shù)據(jù)的方法。這個(gè)程序復(fù)用了代碼清單1-1 中的Cache類,它要做的就是在設(shè)置緩存之前把Python數(shù)據(jù)編碼為JSON數(shù)據(jù),并在獲取緩存之后將JSON數(shù)據(jù)解碼為Python數(shù)據(jù)。

代碼清單1-2 使用JSON實(shí)現(xiàn)的多項(xiàng)數(shù)據(jù)緩存程序json_cache.py

import json
from cache import Cache
 
class JsonCache:
 
    def __init__(self, client):
        self.cache = Cache(client)
 
    def set(self, name, content, ttl=None):
        """
        為指定名字的緩存設(shè)置內(nèi)容。
        可選的ttl參數(shù)用于設(shè)置緩存的存活時(shí)間。
        """
        json_data = json.dumps(content)
        self.cache.set(name, json_data, ttl)
 
    def get(self, name):
        """
        嘗試獲取指定名字的緩存內(nèi)容,若緩存不存在則返回None。
        """
        json_data = self.cache.get(name)
        if json_data is not None:
            return json.loads(json_data)

作為例子,下面這段代碼展示了如何使用上述多項(xiàng)數(shù)據(jù)緩存程序來(lái)緩存前面展示的用戶信息:

>>> from redis import Redis
>>> from json_cache import JsonCache
>>> client = Redis(decode_responses=True)
>>> cache = JsonCache(client)  # 創(chuàng)建緩存對(duì)象
>>> data = {"id":10086, "name": "Peter", "gender": "male", "age": 56}
>>> cache.set("User:10086", data)  # 緩存數(shù)據(jù)
>>> cache.get("User:10086")  # 獲取緩存
{'id': 10086, 'name': 'Peter', 'gender': 'male', 'age': 56}

除了將多項(xiàng)數(shù)據(jù)編碼為JSON后將其存儲(chǔ)在字符串鍵中,還可以直接將多項(xiàng)數(shù)據(jù)存儲(chǔ)在Redis的哈希鍵中。為此,在設(shè)置緩存時(shí)需要用到HSET命令:

HSET name field value [field value] [...]

如果用戶在設(shè)置緩存的同時(shí)還指定了緩存的存活時(shí)間,那么還需要使用EXPIRE命令為緩存設(shè)置過(guò)期時(shí)間,并使用事務(wù)或者其他類似措施保證多個(gè)命令在執(zhí)行時(shí)的安全性:

MULTI
HSET name field value [field value] [...]
EXPIRE name ttl
EXEC

與此相對(duì),當(dāng)要獲取被緩存的多項(xiàng)數(shù)據(jù)時(shí),只需要使用HGETALL命令獲取所有數(shù)據(jù)即可:

HGETALL name

代碼清單1-3展示了基于上述原理實(shí)現(xiàn)的多項(xiàng)數(shù)據(jù)緩存程序。

代碼清單1-3 使用哈希鍵實(shí)現(xiàn)的多項(xiàng)數(shù)據(jù)緩存程序hash_cache.py

class HashCache:
 
    def __init__(self, client):
        self.client = client
 
    def set(self, name, content, ttl=None):
        """
        為指定名字的緩存設(shè)置內(nèi)容。
        可選的ttl參數(shù)用于設(shè)置緩存的存活時(shí)間。
        """
        if ttl is None:
            self.client.hset(name, mapping=content)
        else:
            tx = self.client.pipeline()
            tx.hset(name, mapping=content)
            tx.expire(name, ttl)
            tx.execute()
 
    def get(self, name):
        """
        嘗試獲取指定名字的緩存內(nèi)容,若緩存不存在則返回None。
        """
        result = self.client.hgetall(name)
        if result != {}:
            return result

作為例子,下面這段代碼展示了如何使用上述多項(xiàng)數(shù)據(jù)緩存程序來(lái)緩存前面展示的用戶信息:

>>> from redis import Redis
>>> from hash_cache import HashCache
>>> client = Redis(decode_responses=True)
>>> cache = HashCache(client)
>>> data = {"id":10086, "name": "Peter", "gender": "male", "age": 56}
>>> cache.set("User:10086", data)  # 緩存數(shù)據(jù)
>>> cache.get("User:10086")  # 獲取緩存
{'id': '10086', 'name': 'Peter', 'gender': 'male', 'age': '56'}

可以看到,這個(gè)程序的效果跟之前使用JSON實(shí)現(xiàn)的緩存程序的效果完全一致。

提示:縮短鍵名以節(jié)約內(nèi)存

在使用Redis緩存多項(xiàng)數(shù)據(jù)的時(shí)候,不僅需要緩存數(shù)據(jù)本身(值),還需要緩存數(shù)據(jù)的屬性/字段(鍵)。當(dāng)數(shù)據(jù)的數(shù)量巨大時(shí),緩存屬性的內(nèi)存開銷也會(huì)相當(dāng)巨大。

為此,緩存程序可以通過(guò)適當(dāng)縮短屬性名來(lái)盡可能地減少內(nèi)存開銷。例如,把上面用戶信息中的name屬性縮短為n屬性,age屬性縮短為a屬性,諸如此類。

還有一種更徹底的方法,就是移除數(shù)據(jù)的所有屬性,將數(shù)據(jù)本身存儲(chǔ)為數(shù)組,然后根據(jù)各個(gè)值在數(shù)組中的索引來(lái)判斷它們對(duì)應(yīng)的屬性。例如,可以修改緩存程序,讓它把數(shù)據(jù){"id":10086, "name": "Peter", "gender": "male", "age": 56}簡(jiǎn)化為[10086, "Peter", "male", 56],然后使用JSON數(shù)組或者Redis列表來(lái)存儲(chǔ)簡(jiǎn)化后的數(shù)據(jù)。

主站蜘蛛池模板: 土默特右旗| 诸城市| 加查县| 佛坪县| 石城县| 墨竹工卡县| 巴东县| 昌江| 肇源县| 淳安县| 寿光市| 德兴市| 封丘县| 庆安县| 湖州市| 吉隆县| 新丰县| 京山县| 博白县| 武强县| 星座| 周至县| 青川县| 开远市| 来凤县| 张家港市| 上高县| 藁城市| 奇台县| 湛江市| 凌源市| 儋州市| 凉城县| 砚山县| 千阳县| 韶山市| 乌兰县| 昌乐县| 达尔| 利津县| 深圳市|