- Redis應(yīng)用實(shí)例
- 黃健宏
- 1047字
- 2025-05-26 17:45:10
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ù)。
- 企業(yè)數(shù)字化創(chuàng)新引擎:企業(yè)級(jí)PaaS平臺(tái)HZERO
- Spark快速大數(shù)據(jù)分析(第2版)
- 企業(yè)大數(shù)據(jù)系統(tǒng)構(gòu)建實(shí)戰(zhàn):技術(shù)、架構(gòu)、實(shí)施與應(yīng)用
- 業(yè)務(wù)數(shù)據(jù)分析:五招破解業(yè)務(wù)難題
- 圖解機(jī)器學(xué)習(xí)算法
- 深入淺出MySQL:數(shù)據(jù)庫(kù)開發(fā)、優(yōu)化與管理維護(hù)(第2版)
- Hands-On Mathematics for Deep Learning
- 二進(jìn)制分析實(shí)戰(zhàn)
- 聯(lián)動(dòng)Oracle:設(shè)計(jì)思想、架構(gòu)實(shí)現(xiàn)與AWR報(bào)告
- 數(shù)據(jù)修復(fù)技術(shù)與典型實(shí)例實(shí)戰(zhàn)詳解(第2版)
- 菜鳥學(xué)SPSS數(shù)據(jù)分析
- 云計(jì)算寶典:技術(shù)與實(shí)踐
- MySQL技術(shù)內(nèi)幕:InnoDB存儲(chǔ)引擎
- Delphi High Performance
- Kafka權(quán)威指南(第2版)