使用Redis构建电商网站
涉及到的key:
1. login,hash结构,存储用户token与用户ID之间的映射。
2. recent_tokens,存储最近登陆用户token,zset结构
member: token,score: 登陆时间戳
3. viewed_token,存储token对应用户的浏览商品集合,zset结构,
member: 商品ID,score: 浏览时间戳
4. cart_token, 存储token对应用户的购物车,hash结构,key:商品ID,value: 商品数量
5. schedule, zset结构, member为数据行的行ID,score是一个时间戳,对应何时将指定的数据行缓存到Redis里面
6. delay,zset结构, member为数据行的行ID,score记录了指定数据行的缓存需要每隔多少秒更新一次。
7. viewed, zset结构, member:商品ID, score: 商品浏览次数,用负数表示,浏览次数最高的商品,其索引值为0
# python3
# -*- coding: utf-8 -*- import redis
import time
import json def check_token(conn, token):
return conn.hget('login', token) def update_token(conn, token, user, item=None):
timestamp = time.time()
conn.hset('login', token, user)
conn.zadd('recent_tokens', token, timestamp) # 用户正在浏览的是一个商品页面
if item:
conn.zadd('viewed_' + token, item, timestamp)
# 只保留用户最近浏览过的25个商品
conn.zremrangebyrank('viewed_' + token, 0, -26)
# 采用负数表示页面浏览次数,浏览次数越高的页面,其索引值越小
conn.zincrby('viewed', item, -1) QUIT = False
LIMIT = 10000000 # 应该用守护进程来执行这个函数或者做成定时任务
#清除内容包括: recent_tokens,login,用户对应的浏览记录、购物车
def clean_full_session(conn):
while not QUIT:
size = conn.zcard('recent_tokens')
if size <= LIMIT:
time.sleep(1)
continue end_index = min(size - LIMIT, 100)
sessions = conn.zrange('recent_tokens', 0, end_index - 1) session_keys = []
for sess in sessions:
session_keys.append('viewed_' + sess)
session_keys.append('cart_' + sess) conn.delete(*session_keys)
conn.hdel('login', *sessions)
conn.zrem('recent_tokens', *sessions) # 添加商品到购物车
def add_to_cart(conn, session, item, count):
if count <= 0:
conn.hrem('cart_' + session, item)
else:
conn.hset('cart_' + session, item, count) def can_cache(conn,request):
item_id = extract_item_id(request)
if not item_id or is_dynamic(request):
return False
rank = conn.zrank('viewed', item_id)
return rank is not None and rank < 1000 def cache_request(conn, request, callback):
if not can_cache(conn,request):
return callback(request) page_key = 'cache_' + hash_request(request)
content = conn.get(page_key) if not content:
content = callback(request)
conn.setex(page_key, content, 300) return content def schedule_row_cache(conn, row_id, delay):
conn.zadd('delay', row_id, delay)
conn.zadd('schedule', row_id, time.time()) # 守护进程方式运行或做成定时任务
def cache_rows(conn):
while not QUIT:
next = conn.zrange('schedule', 0, 0, withscores=True)
now = time.time()
if not next or next[0][1] > now:
time.sleep(.05)
continue row_id = next[0][0] delay = conn.zscore('delay', row_id)
if delay <= 0:
conn.zrem('delay', row_id)
conn.zrem('schedule', row_id)
conn.delete('inv_' + row_id)
continue row = Inventory.get(row_id)
conn.zadd('schedule', row_id, now + delay)
conn.set('inv_' + row_id, json.dumps(row.to_dict())) def rescale_viewed(conn):
while not QUIT:
# 保留浏览次数最低的20000个商品
conn.zremrangebyrank('viewed', 0, -20001)
conn.zinterstore('viewed', {'viewed': .5})
time.sleep(300) r = redis.Redis(host='redis_serverip', port=6379, password='redis_passwd', db=0)
参考资料:
《Redis实战》
使用Redis构建电商网站的更多相关文章
- 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念
一.前言 DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...
- 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域
一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...
- 如何一步一步用DDD设计一个电商网站(二)—— 项目架构
阅读目录 前言 六边形架构 终于开始建项目了 DDD中的3个臭皮匠 CQRS(Command Query Responsibility Segregation) 结语 一.前言 上一篇我们讲了DDD的 ...
- REDIS 在电商中的实际应用场景(转)
1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc),Redis的命令都是原子性的,你可以轻松地利用INCR,DECR等 ...
- php+redis实现电商秒杀功能
这一次总结和分享用Redis实现分布式锁来完成电商的秒杀功能.先扯点个人观点,之前我看了一篇博文说博客园的文章大部分都是分享代码,博文里强调说分享思路比分享代码更重要(貌似大概是这个意思,若有误请谅解 ...
- Redis在电商中的实际应用-Java
示例代码用Jedis编写. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc),Redis的命令都是原子性的,你可以轻 ...
- TP5使用Redis处理电商秒杀
本篇文章介绍了ThinkPHP使用Redis实现电商秒杀的处理方法,具有一定的参考价值,希望对学习ThinkPHP的朋友有帮助! TP5使用Redis处理电商秒杀 1.首先在TP5中创建抢购活动所需要 ...
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
随机推荐
- 2、使用断言(json assertion)
1.假设现在有一个服务端的返回数据(需要测试的)为:HTTP/1.1 200 OK,要测试的响应字段勾选Response Headers,模式匹配规则选择Substring,把该响应断言命名为Http ...
- 用Jenkins集成ios项目设置多scheme,同一代码自动输出多个环境包 实现便捷切换API环境
Jenkins 安装使用参考我的博客http://www.cnblogs.com/zhujin/p/9064820.html Xcode 配置:说明 一个schema 对应一套环境(如生产,测试),一 ...
- 面试 HTTP ,99% 的面试官都爱问这些问题
HTTP 和 HTTPS 的区别 HTTP 是一种 超文本传输协议(Hypertext Transfer Protocol),HTTP 是一个在计算机世界里专门在两点之间传输文字.图片.音频.视频等超 ...
- Salesforce Spring '20新功能集锦系列(二)
一.使用Data Mask保护沙盒数据 对于Salesforce管理员和开发人员,Data Mask是功能强大的新数据安全资源.管理员可以使用数据掩码自动加密沙盒中的数据,无需手动保护数据和沙盒组织的 ...
- Websocket直播间聊天室教程 - GoEasy快速实现聊天室
最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...
- SQL入门,就这么简单
随着时代的发展,人类活动产生的信息越来越多,大家常说,现在这个时代是大数据时代.在这样一个前提下,数据的存储成为我们必须要认真对待和研究的问题了.SQL(Structured Query Langua ...
- JAVA的synchronized写法
使用关键字synchronized的写法比较多,常用的有如下几种,代码如下: public class MyService { synchronized public static void test ...
- git基本设置——git工具篇
1.设置邮箱和用户名 /*解释: --global 选项代表对 Git 进行全局设置.*/ $ git config --global user.name "Your Name" ...
- Jquery中 $.Ajax() 参数详解
1.url:要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type:要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如pu ...
- 如何使用IE9浏览器自带开发人员工具捕获网页请求
我们在通过浏览器访问一个网页的时候,有时候会遇到页面不能正常显示,图片不能正常加载的问题. 如果我们需要知道浏览器打开该网页时,网页中每个元素的加载情况.这时,我们便可以借助浏览器自带开发人员工具,来 ...