使用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设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
随机推荐
- java day04记录
本文主要记录arr数组用法.count计算.arr倒排序技巧案例 package day4homework; import java.util.Scanner; /* 从键盘上输入10个整数,合法值位 ...
- "文本"组件:<text> —— 快应用原生组件
 <template> <div class="container"> <text>H-UI</text> </div> ...
- not found 什么时候触发
eq: BEGIN DECLARE EXIT HANDLER FOR NOT FOUND SET o_state = 999; select count(1) into ...
- flex实现三列布局
css3新引入的flex在某些情况下布局非常实用 因为它是弹性盒子所以自适应效果会很棒 不过各项布局方案还是各有优劣 <!DOCTYPE html> <html lang=" ...
- 多线程设置flag标志位实现同步
信号灯解决同步问题 我尽量注释了代码,可以很容易理解了. package Thread; /** * 信号灯 * 借助标志位 */ public class FlagThread { public s ...
- re模块语法—python正则表达式
用字符串匹配实现 对于简单的匹配查找,可以通过字符串匹配实现,比如:查找以”hello”开头的字符串 此时就可以正确查找出以start开始的字符串了 python中的正则表达式模块 在python中为 ...
- C - Dr. Evil Underscores CodeForces - 1285D 二进制
题目大意:n个数,任意整数x对这n个数取异或值,然后使最大值最小. 思路:数据范围最大为pow(2,30);所以考虑二进制的话,最多有30位.对于某一位d,然后考虑数组v中每一个元素的d为是0还是1, ...
- js多线程的实现
我们都知道JS是一种单线程语言,即使是一些异步的事件也是在JS的主线程上运行的(具体是怎么运行的,可以看我另一篇博客JS代码运行机制).像setTimeout.ajax的异步请求,或者是dom元素的一 ...
- 【转】动态规划之最长公共子序列(LCS)
[原文链接]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套 ...
- Spring5:概念
1.Spring优点 spring是一个开源的免费的框架 spring是一个轻量级的 非入侵式的框架 控制反转(IOC).面向切面(AOP) 支持事务的处理,对框架整合的支持 **总之:spring就 ...