Skip to content

Commit 61d01ca

Browse files
committed
购物网站缓存页面
1 parent fd271a0 commit 61d01ca

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

shopping_website/README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,22 @@
1717

1818
我们把购物车的信息也存储到Redis,并且使用与用户会话令牌一样的cookie id来引用购物车。
1919

20+
将用户和购物车都存储到Redis里面,这种做法除了可以减少请求体积外,我们可以根据用户浏览过的商品,用户放入购物车的商品以及用户最终购买的商品进行统计计算,并构建起很多大型网络零售上都在提供的”在查看过这件商品的用户当中,有X%的用户最终购买了这件商品“”购买了这件商品的用户也购买了某某其他商品“等功能,这些功能可以帮助用户查找其他相关的商品,并最终提升网站的销售业绩。
21+
22+
#### (3)网页缓存 ####
23+
24+
购物网站上多数页面实际上并不会经常发生大变化,虽然会向分类中添加新商品、移除旧商品、有时候特价促销、有时甚至还有”热卖商品“页面,但是在一般情况下,网站只有账号设置、以往订单、购物车(结账信息)以及其他少数几个页面才包含需要每次载入都要动态生成的内容。
25+
26+
对于不需要动态生成的页面,我们需要尽量不再生成,减少网站在动态生成内容上面所花的时间,可以降低网站处理相同负载所需的服务器数量,让网站速度加快。
27+
28+
python应用框架大都存在中间件,我们创建中间件来调用Redis缓存函数:对于不能被缓存的请求,直接生成并返回页面,对于可以被缓存的请求,先从缓存取出缓存页面,如果缓存页面不存在,那么会生成页面并将其缓存在Redis,最后将页面返回给函数调用者。
29+
2030
* Redis设计 *
2131
(1)登录令牌与用户映射关系的散列 "login:"
2232
(2)记录最近登录用户的有序集合 "recent:"
2333
(3)记录各个用户最近浏览商品的有序集合 "viewed:94233rhsYRIq3yi3qryrye"
2434
(4)每个用户的购物车散列,存储商品ID与商品订购数量之间的映射。"cart:94233rhsYRIq3yi3qryrye"
35+
(5)请求页面缓存集合 "cache:wre9w3rieruerwe3" (wre9w3rieruerwe3代表请求ID)
2536

2637
(94233rhsYRIq3yi3qryrye假设为某个用户的令牌)
2738

@@ -35,12 +46,16 @@
3546
(3)存储会话的内存会随着时间的推移而不断增加,需要定期清理会话数据,我们决定只保留最新的1000万个会话。
3647

3748
我们可以用 *守护进程的方式来运行或者定义一个cron job每隔一段时间运行*
38-
检查最近 “记录最近登录用户的有序集合” 大小是否超过了限制,超过限制每秒从集合中删除最旧的100个令牌,并且移除相应的“登录令牌与用户映射关系的散列”的信息和对应的“记录各个用户最近浏览商品的有序集合”。
49+
检查最近 “记录最近登录用户的有序集合” 大小是否超过了限制,超过限制每秒从集合中删除最旧的100个令牌,并且移除相应的“登录令牌与用户映射关系的散列”的信息和对应的“记录各个用户最近浏览商品的有序集合”,对应的”美国用户的购物车散列“
3950

4051
我们也可以使用EXPIRE命令,为用户令牌设记录用户商品浏览记录的有序集合设置过期时间,让Redis在一段时间之后自动删除它们,这样就不用使用有序集合来记录最近出现的令牌了,但是这样我们就没办法将会话数限制在1000万之内了。
4152

4253
(4)对购物车进行更新,如果用户订购某件商品数量大于0,将商品信息添加到 “用户的购物车散列”中,如果购买商品已经存在,那么更新购买数量。
4354

55+
(5)在用户请求页面时,对于不能被缓存的请求,直接生成并返回页面,对于可以被缓存的请求,先从缓存取出缓存页面,如果缓存页面不存在,那么会生成页面并将其缓存在Redis,最后将页面返回给函数调用者。
56+
57+
58+
4459

4560

4661
* Redis设计 *

shopping_website/shopping_website.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ def clearSession(conn):
6565
end_index = min(size - LIMIT, 100)
6666
tokens = conn.zrange('recent:', 0, end_index - 1)
6767

68+
# 将要删除的key都推入到数组中,要时候一起删除
6869
session_keys = []
6970
for token in tokens:
7071
session_keys.append('viewed:' + token)
72+
session_keys.append('cart:' + token)
7173

72-
# 批量删除相应的用户最近浏览商品有序集合,登录令牌与用户映射关系的散列和记录最近登录用户的有序集合
74+
# 批量删除相应的用户最近浏览商品有序集合,用户的购物车,登录令牌与用户映射关系的散列和记录最近登录用户的有序集合
7375
conn.delete(*session_key)
7476
conn.hdel('login:', *tokens)
7577
conn.zrem('recent:', *tokens)
@@ -78,6 +80,10 @@ def clearSession(conn):
7880
对购物车进行更新,如果用户订购某件商品数量大于0,将商品信息添加到 “用户的购物车散列”中,如果购买商品已经存在,那么更新购买数量
7981
8082
@param {object}
83+
@param {string} session
84+
@param {string} item
85+
@param {float} count
86+
8187
"""
8288
def addToCart(conn, session, item, count):
8389
if count <= 0:
@@ -86,4 +92,30 @@ def addToCart(conn, session, item, count):
8692
else:
8793
# 将指定商品添加到对应的购物车中
8894
conn.hset('cart:' + session, item, count)
95+
96+
"""
97+
在用户请求页面时,对于不能被缓存的请求,直接生成并返回页面,
98+
对于可以被缓存的请求,先从缓存取出缓存页面,如果缓存页面不存在,那么会生成页面并将其缓存在Redis,最后将页面返回给函数调用者。
99+
100+
@param {object} conn
101+
@param {string} request
102+
@param {callback}
103+
104+
@return
105+
"""
106+
def cacheRequest(conn, request, callback):
107+
# 判断请求是否能被缓存,不能的话直接调用回调函数
108+
if not canCache(request):
109+
return callback(request)
110+
111+
# 将请求转换为一个简单的字符串健,方便之后进行查找
112+
page_key = 'cache:' + hash_request(request)
113+
content = conn.get(page_key)
114+
115+
# 没有缓存的页面,调用回调函数生成页面,并缓存到redis中
116+
if not content:
117+
content = callback(request)
118+
conn.setex(page_key, content, 300)
119+
120+
return content
89121

0 commit comments

Comments
 (0)