第二章 使用Redis构建web应用(案例分析)
2.1 登录和cookie缓存
- 登录时验证token令牌
- 用户每次浏览页面,保存用户浏览时间
- 用户浏览商品页,将商品保存到最近浏览,并限额25个
- 定期清理token令牌,最大保存1000万个(
守护进程触发
,超过能移除最多100个最旧令牌,并从散列中删除令牌对应的用户信息,最近浏览商品也进行存储,未超过休眠1s)
- hash 登录token(token、userID)
- zset 最近登录用户(token、浏览页面的时间戳)
- zset 最近浏览商品(商品ID、浏览商品的时间戳)
# 尝试获取并返回令牌对应的用户,这里有漏洞,应该判断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 = FalseLIMIT = 10000000def 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