涉及到的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

  1. # python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import redis
  5. import time
  6. import json
  7.  
  8. def check_token(conn, token):
  9. return conn.hget('login', token)
  10.  
  11. def update_token(conn, token, user, item=None):
  12. timestamp = time.time()
  13. conn.hset('login', token, user)
  14. conn.zadd('recent_tokens', token, timestamp)
  15.  
  16. # 用户正在浏览的是一个商品页面
  17. if item:
  18. conn.zadd('viewed_' + token, item, timestamp)
  19. # 只保留用户最近浏览过的25个商品
  20. conn.zremrangebyrank('viewed_' + token, 0, -26)
  21. # 采用负数表示页面浏览次数,浏览次数越高的页面,其索引值越小
  22. conn.zincrby('viewed', item, -1)
  23.  
  24. QUIT = False
  25. LIMIT = 10000000
  26.  
  27. # 应该用守护进程来执行这个函数或者做成定时任务
  28. #清除内容包括: recent_tokens,login,用户对应的浏览记录、购物车
  29. def clean_full_session(conn):
  30. while not QUIT:
  31. size = conn.zcard('recent_tokens')
  32. if size <= LIMIT:
  33. time.sleep(1)
  34. continue
  35.  
  36. end_index = min(size - LIMIT, 100)
  37. sessions = conn.zrange('recent_tokens', 0, end_index - 1)
  38.  
  39. session_keys = []
  40. for sess in sessions:
  41. session_keys.append('viewed_' + sess)
  42. session_keys.append('cart_' + sess)
  43.  
  44. conn.delete(*session_keys)
  45. conn.hdel('login', *sessions)
  46. conn.zrem('recent_tokens', *sessions)
  47.  
  48. # 添加商品到购物车
  49. def add_to_cart(conn, session, item, count):
  50. if count <= 0:
  51. conn.hrem('cart_' + session, item)
  52. else:
  53. conn.hset('cart_' + session, item, count)
  54.  
  55. def can_cache(conn,request):
  56. item_id = extract_item_id(request)
  57. if not item_id or is_dynamic(request):
  58. return False
  59. rank = conn.zrank('viewed', item_id)
  60. return rank is not None and rank < 1000
  61.  
  62. def cache_request(conn, request, callback):
  63. if not can_cache(conn,request):
  64. return callback(request)
  65.  
  66. page_key = 'cache_' + hash_request(request)
  67. content = conn.get(page_key)
  68.  
  69. if not content:
  70. content = callback(request)
  71. conn.setex(page_key, content, 300)
  72.  
  73. return content
  74.  
  75. def schedule_row_cache(conn, row_id, delay):
  76. conn.zadd('delay', row_id, delay)
  77. conn.zadd('schedule', row_id, time.time())
  78.  
  79. # 守护进程方式运行或做成定时任务
  80. def cache_rows(conn):
  81. while not QUIT:
  82. next = conn.zrange('schedule', 0, 0, withscores=True)
  83. now = time.time()
  84. if not next or next[0][1] > now:
  85. time.sleep(.05)
  86. continue
  87.  
  88. row_id = next[0][0]
  89.  
  90. delay = conn.zscore('delay', row_id)
  91. if delay <= 0:
  92. conn.zrem('delay', row_id)
  93. conn.zrem('schedule', row_id)
  94. conn.delete('inv_' + row_id)
  95. continue
  96.  
  97. row = Inventory.get(row_id)
  98. conn.zadd('schedule', row_id, now + delay)
  99. conn.set('inv_' + row_id, json.dumps(row.to_dict()))
  100.  
  101. def rescale_viewed(conn):
  102. while not QUIT:
  103. # 保留浏览次数最低的20000个商品
  104. conn.zremrangebyrank('viewed', 0, -20001)
  105. conn.zinterstore('viewed', {'viewed': .5})
  106. time.sleep(300)
  107.  
  108. 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. java day04记录

    本文主要记录arr数组用法.count计算.arr倒排序技巧案例 package day4homework; import java.util.Scanner; /* 从键盘上输入10个整数,合法值位 ...

  2. "文本"组件:<text> —— 快应用原生组件

     <template> <div class="container"> <text>H-UI</text> </div> ...

  3. not found 什么时候触发

    eq: BEGIN        DECLARE EXIT HANDLER FOR NOT FOUND SET o_state = 999;         select count(1) into ...

  4. flex实现三列布局

    css3新引入的flex在某些情况下布局非常实用 因为它是弹性盒子所以自适应效果会很棒 不过各项布局方案还是各有优劣 <!DOCTYPE html> <html lang=" ...

  5. 多线程设置flag标志位实现同步

    信号灯解决同步问题 我尽量注释了代码,可以很容易理解了. package Thread; /** * 信号灯 * 借助标志位 */ public class FlagThread { public s ...

  6. re模块语法—python正则表达式

    用字符串匹配实现 对于简单的匹配查找,可以通过字符串匹配实现,比如:查找以”hello”开头的字符串 此时就可以正确查找出以start开始的字符串了 python中的正则表达式模块 在python中为 ...

  7. C - Dr. Evil Underscores CodeForces - 1285D 二进制

    题目大意:n个数,任意整数x对这n个数取异或值,然后使最大值最小. 思路:数据范围最大为pow(2,30);所以考虑二进制的话,最多有30位.对于某一位d,然后考虑数组v中每一个元素的d为是0还是1, ...

  8. js多线程的实现

    我们都知道JS是一种单线程语言,即使是一些异步的事件也是在JS的主线程上运行的(具体是怎么运行的,可以看我另一篇博客JS代码运行机制).像setTimeout.ajax的异步请求,或者是dom元素的一 ...

  9. 【转】动态规划之最长公共子序列(LCS)

    [原文链接]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套 ...

  10. Spring5:概念

    1.Spring优点 spring是一个开源的免费的框架 spring是一个轻量级的 非入侵式的框架 控制反转(IOC).面向切面(AOP) 支持事务的处理,对框架整合的支持 **总之:spring就 ...