共计 1409 个字符,预计需要花费 4 分钟才能阅读完成。
第二章 使用 Redis 构建 web 应用(案例分析)
2.1 登录和 cookie 缓存
- 业务分析
- 登录时验证 token 令牌
- 用户每次浏览页面,保存用户浏览时间
- 用户浏览商品页,将商品保存到最近浏览,并限额 25 个
- 定期清理 token 令牌,最大保存 1000 万个 (
守护进程触发
,超过能移除最多 100 个最旧令牌,并从散列中删除令牌对应的用户信息,最近浏览商品也进行存储,未超过休眠 1s)
- 数据构建设计
- hash 登录 token(token、userID)
- zset 最近登录用户(token、浏览页面的时间戳)
- zset 最近浏览商品(商品 ID、浏览商品的时间戳)
- 代码实现 python
# 尝试获取并返回令牌对应的用户,这里有漏洞,应该判断 token 是否合法,并不能仅仅判断 Redis 中是否有无
def check_token(conn,token):
return conn.hget('login:',token)
# 更新 token, 并保持最近浏览时间,和最近浏览商品
def update_token(conn,token,user,item=None):
timestamp = time.time()
conn.hset('login:',token,user)
conn.zadd('recent:',token,timestamp)
if item :
conn.zadd('viewed:' + token,item,timestamp)
conn.zremrangebyrank('viewed:' + token,0,-26)
# 循环清理超数量令牌
QUIT = False
LIMIT = 10000000
def clean_sessions(conn):
while not QUIT:
size = conn.zcard('recent:')
if size < LIMIT
time.sleep(1)
continue
# 获取删除的个数,没到 100,就选 size-LIMIT,超过 100 就选 100
end_index = min(size - LIMIT,100)
tokens = conn.zrange('recent:',0,end_index-1)
session_keys = []
for token in tokens:
session_keys.append('viewed:' + 'token')
# 删除最近浏览商品
conn.delete(*session_keys)
# 删除登录 token
conn.hdel('login:',*token)
# 删除最近浏览页面记录
conn.zrem('recent:',*token)
2.2 网页缓存(静态化)
- 数据结构设计:存储在 string 中
- 代码实现 Python
# callback- 对于不能被缓存的数据,可直接调用回调函数
def cache_request(conn,request,callback):
if not can_cache(conn,request):
return callback(request)
# 将 request 请求转换成字符串,方便查找
page_key = 'cache:' + hash_request(request)
# 尝试查找被缓存页面,
content = conn.get(page_key)
if not content :
content = callback(request)
# 将新生成页面放在缓存中,并设置 5 分钟过期
conn.setx(page_key,content,300)
return content
正文完