使用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设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
随机推荐
- vscode连接云服务,搭建Python远程开发
配置Python远程开发环境前提 配置步骤 1.windows 10 开发机配置 win10 1809后支持ssh ssh-keygen -t rsa -b 4096 #会显示生成到的目录C:\Use ...
- react性能优化最佳实践
1.PureComponent 的使用场景 PureComponent 和 Component 的区别是,PureComponent 自带 shouldComponentUpdate 生命周期函数,会 ...
- B - How Many Equations Can You Find dfs
Now give you an string which only contains 0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9.You are asked to add the sig ...
- 原创hadoop2.6.4 namenode HA+Federation集群高可用部署
今天下午刚刚搭建了一个高可用hadoop集群,整理如下,希望大家能够喜欢. namenode HA:得有两个节点,构成一个namenode HA集群 namenode Federation:可以有 ...
- win10下cuda安装以及利用anaconda安装pytorch-gpu过程
安装环境:win10+2070super 1.Cuda的下载安装及配置 (1)测试本机独立显卡是否支持CUDA的安装,点击此处查询显卡是否在列表中. (2)查看自己是否能右键找到NVIDA控制面板,如 ...
- 【Vue】状态管理
页面应用需要Vuex管理全局/模块的状态,大型单页面组件如果靠事件(events)/属性(props)通讯传值会把各个组件耦合在一起.因 此需要Vuex统一管理,当然如是小型单页面应用,引用Vuex反 ...
- pysparnn 模块使用,相似句子召回
import pysparnn.cluster_index as ci from sklearn.feature_extraction.text import TfidfVectorizer data ...
- Java 自动拆箱 装箱 包装类的缓存问题--结合源码分析
都0202 了 java 1.8 已经是主流 自动装箱 .拆箱已经很普遍使用了,那么有时候是不是会遇到坑呢? 我们先来看一段代码: public class TestWraperClass { pub ...
- jdbc-手写Java方法连接数据库
一.关键四元素 ① com.mysql.jdbc.Driver mysql数据库连接jar包. 获取途径: 链接:https://pan.baidu.com/s/1SFcjuu ...
- debian7安装了mysql后,局域网去连接时出现10061错误