涉及到的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构建电商网站的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    一.前言     DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...

  2. 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

    一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...

  3. 如何一步一步用DDD设计一个电商网站(二)—— 项目架构

    阅读目录 前言 六边形架构 终于开始建项目了 DDD中的3个臭皮匠 CQRS(Command Query Responsibility Segregation) 结语 一.前言 上一篇我们讲了DDD的 ...

  4. REDIS 在电商中的实际应用场景(转)

    1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc),Redis的命令都是原子性的,你可以轻松地利用INCR,DECR等 ...

  5. php+redis实现电商秒杀功能

    这一次总结和分享用Redis实现分布式锁来完成电商的秒杀功能.先扯点个人观点,之前我看了一篇博文说博客园的文章大部分都是分享代码,博文里强调说分享思路比分享代码更重要(貌似大概是这个意思,若有误请谅解 ...

  6. Redis在电商中的实际应用-Java

    示例代码用Jedis编写. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc),Redis的命令都是原子性的,你可以轻 ...

  7. TP5使用Redis处理电商秒杀

    本篇文章介绍了ThinkPHP使用Redis实现电商秒杀的处理方法,具有一定的参考价值,希望对学习ThinkPHP的朋友有帮助! TP5使用Redis处理电商秒杀 1.首先在TP5中创建抢购活动所需要 ...

  8. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  9. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

随机推荐

  1. 第一章:shell脚本初入门

    1.shell脚本中的source或者.空格再加上文件,表示加载文件中的命令及语句(困惑多时终于解开^-^) 2.脚本开头书写好作者版本等信息,方便维护:流程语句提前把格式写好,防止遗漏 3.定义字符 ...

  2. 【three.js第四课】自定义材料、贴图。

    1.先去下载6张不同的图片素材放到项目中. 2.在[three.js第三课]的代码基础上添加自定义的材料 //自定义材料 cubeMaterial 数组 //map:用于加载图片,THREE.Text ...

  3. windows/linux下如何更换Python的pip源

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:xlixiaohui PS:如有需要Python学习资料的小伙伴可以 ...

  4. Daily Scrum 12/24/2015

    Process: Zhaoyang: Some UI change and compile the Caffe in the IOS. Yandong: Do some code integratio ...

  5. overload 与override的区别

    Override  是重写: 方法名称.参数个数,类型,顺序,返回值类型都是必须和父类方法一致的.它的关系是父子关系Overload 是重载:  方法名称不变,其余的都是可以变更的.它的关系是同一个类 ...

  6. NCTF2019 小部分题解

    前言 礼拜五领航杯打的比较累,做不出WEB,D3CTF没用,做了NJCTF的一些题目(懒,睡觉到12点起) Misc 第一次比赛先去做misc,以前一直做WEB,以后要WEB+MISC做.礼拜六下午做 ...

  7. java集合List

    需求:List集合存储字符串并遍历.List集合的特点: 有序(存储和取出的元素一致),可重复的.package javatest; import java.util.ArrayList;import ...

  8. TensorFlow keras vgg16net的使用

    from tensorflow.python.keras.applications.vgg16 import VGG16,preprocess_input,decode_predictions fro ...

  9. 聊聊JavaScript在工作中常用的方法(一)

    一.字符串转数组(split方法) 废话少说,直接上代码: //例子1 var str="abc,def,ghi"; var strArray=str.split(",& ...

  10. [leetcode] 并查集(Ⅰ)

    预备知识 并查集 (Union Set) 一种常见的应用是计算一个图中连通分量的个数.比如: a e / \ | b c f | | d g 上图的连通分量的个数为 2 . 并查集的主要思想是在每个连 ...