使用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设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
随机推荐
- 22 Extends 继承(子类、父类)
本章主要介绍继承的 概念.方法重写(@Override注解的使用).使用场景.方法的执行顺序 /*1.继承的 概念 * 继承:多个类有共同的成员变量和成员方法,抽取到另外一个类中(父类),在让多个类去 ...
- 2020-3-3 20175110王礼博 《网络对抗技术》Exp1 PC平台逆向破解
目录 1.实践目标与基础知识 2.直接修改程序机器指令,改变程序执行流程 3.通过构造输入参数,造成BOF攻击,改变程序执行流 4.注入Shellcode并执行 5.实验收获与感想 6.什么是漏洞?漏 ...
- "视频播放器"组件:<video-player> —— 快应用组件库H-UI
 <import name="video-player" src="../Common/ui/h-ui/media/c_video_player"> ...
- k8s Service学习
service的概念 kubernetes service定义了一个抽象概念,一个pod的逻辑分组,一种可以访问的策略---通常称为服务.这组pod能够被service访问到,通常通过label se ...
- zookeeper的下载安装和选举机制(zookeeper一)
1. 简要概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的框架.Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架它负责存储和管理大家都关心的 ...
- 自己总结 :并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结
并发队列ConcurrentLinkedQueue.阻塞队列AraayBlockingQueue.阻塞队列LinkedBlockingQueue 区别 和 使用场景总结 分类: Java2013-0 ...
- 数据结构和算法(Golang实现)(13)常见数据结构-可变长数组
可变长数组 因为数组大小是固定的,当数据元素特别多时,固定的数组无法储存这么多的值,所以可变长数组出现了,这也是一种数据结构.在Golang语言中,可变长数组被内置在语言里面:切片slice. sli ...
- 014-预处理指令-C语言笔记
014-预处理指令-C语言笔记 学习目标 1.[掌握]枚举 2.[掌握]typedef关键字 3.[理解]预处理指令 4.[掌握]#define宏定义 5.[掌握]条件编译 6.[掌握]static与 ...
- Linux环境下django初入
python -m pip install --upgrade pip 终端中 一. 创建项目: 1.django-admin startproject mysite(第一种比较好) 2.django ...
- day18作业
作业: # 1.编写课上讲解的有参装饰器准备明天默写 def auth(file_type): def outer(func): def inter(*args,**kwargs): if file_ ...