设计亚马逊按销售排名功能

1: 定义 Use Cases 和 约束

Use cases

作用域内的Use Case
  • Service 通过目录计算过去一周内最受欢迎的产品
  • User 通过目录去View过去周内最受欢迎的产品
  • Service 有高可用
作用域外
  • 整个电商网站
    • 设计组件(只是计算销售排名)

约束和假设

  • Traffic 不是平均分布的
  • 类目会被存进多个不同目录
  • 类目不能改变目录
  • 没有子目录,比如: foo/bar/baz
  • 结果会被定时更新
    • 更受换一个的产品或许需要更频繁的更新
  • 1000 万产品
  • 1000 目录
  • 10 亿交易 / 月
  • 1000 亿 请求 / 月
  • 100:1读写比率

计算使用量

  1. 每个 trasnaction 的 Size

    • created_at - 5 bytes
    • product_id - 8 bytes
    • category_id - 4 bytes
    • seller_id - 8 bytes
    • buyer_id - 8 bytes
    • quantity - 4 bytes
    • total_price - 5 bytes
    • Total: ~40 bytes
  2. 每个月有 40 GB 的新 trasnaction 内容

  • 40 字节 / transaction * 10 亿 transaction / 月
  • 1.44 TB 新 transaction 内容 / 3 年
  • 假设大部分是新的交易,而不是更新已经存在的
  1. 平均 400 transaction / s
  2. 平均 40000 读请求 / s

便利转换指南:

  • 每个月有250万秒
  • 1 request / s = 250 万 请求 / 月
  • 40 request / s = 1 亿请求每月
  • 400 request / s = 10 亿请求每月

2:创建一个High Level设计

Design

3: 设计核心组件

Use case: Service 通过category计算过去周内最受欢迎的产品

我们可以我们可以存储二进制 Sales API server的 log 文件进受管理的独享存储,比如 Amazon S3, 而不是管理我们自己的分布式文件系统

我们将假设这是一个简单的 log entry, tab delimited:

timestamp   product_id  category_id    qty     total_price   seller_id    buyer_id
t1          product1    category1      2       20.00         1            1
t2          product1    category2      2       20.00         2            2
t2          product1    category2      1       10.00         2            3
t3          product2    category1      3        7.00         3            4
t4          product3    category2      7        2.00         4            5
t5          product4    category1      1        5.00         5            6

Sales Rank Service 会使用 MapReduce, 使用这个 Sales API Sever的 log 文件作为输入,而且结果会被写进聚合表 sales_rank. 我们应该讨论数据库是选用SQL 还是NoSQL.

我们将使用多步骤的 MapReduce:

  • Step1: 转移数据到 `(category, produce_id), sum(quantity)
  • Step2: 执行分布式排序
class SalesRanker(MRJob):def within_past_week(self, timestamp):"""Return True if timestamp is within past week, False otherwise."""...def mapper(self, _ line):"""Parse each log line, extract and transform relevant lines.Emit key value pairs of the form:(category1, product1), 2(category2, product1), 2(category2, product1), 1(category1, product2), 3(category2, product3), 7(category1, product4), 1"""timestamp, product_id, category_id, quantity, total_price, seller_id, \buyer_id = line.split('\t')if self.within_past_week(timestamp):yield (category_id, product_id), quantitydef reducer(self, key, value):"""Sum values for each key.(category1, product1), 2(category2, product1), 3(category1, product2), 3(category2, product3), 7(category1, product4), 1"""yield key, sum(values)def mapper_sort(self, key, value):"""Construct key to ensure proper sorting.Transform key and value to the form:(category1, 2), product1(category2, 3), product1(category1, 3), product2(category2, 7), product3(category1, 1), product4The shuffle/sort step of MapReduce will then do adistributed sort on the keys, resulting in:(category1, 1), product4(category1, 2), product1(category1, 3), product2(category2, 3), product1(category2, 7), product3"""category_id, product_id = keyquantity = valueyield (category_id, quantity), product_iddef reducer_identity(self, key, value):yield key, valuedef steps(self):"""Run the map and reduce steps."""return [self.mr(mapper=self.mapper,reducer=self.reducer),self.mr(mapper=self.mapper_sort,reducer=self.reducer_identity),]

这个结果将变成下面的 sorted list, 我们可以插入 sales_rank 表中:

(category1, 1), product4
(category1, 2), product1
(category1, 3), product2
(category2, 3), product1
(category2, 7), product3

sales_rank table 会有如下的结构:

id int NOT NULL AUTO_INCREMENT
category_id int NOT NULL
total_sold int NOT NULL
product_id int NOT NULL
PRIMARY KEY(id)
FOREIGN KEY(category_id) REFERENCES Categories(id)
FOREIGN KEY(product_id) REFERENCES Products(id)

我们将创建一个index在id, category_id, and product_id 上去加速查询(log 时间而不是扫描整张表)
,而且放进数据去内存。从内存中序列化的读取数据需要250微妙,当从SSD读取需要4倍,从磁盘读取需要80倍。

Use Case: User 通过目录查看过去一周内最受欢迎的产品
  • Client 发送请求到Web Server
  • Web Server 转发请求到 Read API server
  • Read API server 从数据库表 sales_rank 重读取数据

我们可以使用如下Rest API:

$ curl https://amazon.com/api/v1/popular?category_id=1234

Response:

{"id": "100","category_id": "1234","total_sold": "100000","product_id": "50",
},
{"id": "53","category_id": "1234","total_sold": "90000","product_id": "200",
},
{"id": "75","category_id": "1234","total_sold": "80000","product_id": "3",
}

4: 扩展设计

Extend Design

分析数据库可以使用数据仓库解决方案,如Amazon Redshift或Google BigQuery。

我们可能只想在数据库中存储有限时间段的数据,而将剩余数据存储在数据仓库或对象存储中。像亚马逊S3这样的对象存储可以轻松应对每月40 GB新内容的限制。

为了解决每秒 40,000 个平均读取请求(峰值更高),流行内容(及其销售排名)的流量应由内存缓存而不是数据库处理。内存缓存对于处理分布不均的流量和流量尖峰也很有效。由于读取量很大,SQL 读取副本可能无法处理缓存缺失。我们可能需要采用额外的 SQL 扩展模式。

对于单个SQL写主从架构来说,每秒400次平均写入(峰值更高)可能很困难,这也表明需要额外的扩展技术。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/422561.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows云服务器如何配置多用户登录?(Windows 2012)华为云官方文档与视频地址

Windows云服务器如何配置多用户登录?(Windows 2012)_弹性云服务器 ECS_故障排除_多用户登录_华为云 打开任务栏左下角的“服务器管理器”,在左侧列表中选中“本地服务器” 然后将右侧“远程桌面”功能的选项修改为“启用”&#x…

插混、增程、纯电为什么说纯电是未来的趋势

技术路线:插混、增程、纯电趋势判断 新能源汽车目前有纯电动、增程式、插电式3 种主流技术路径,其中增程式和插电式均为混动技术。纯电动汽车是指以动力电池为动力,用电机驱动车轮行驶;混动技术分为串联、并联、混联3 种模式&…

计算机网络——第四层:传输层以及TCP UDP

1. 传输层的协议 1.1 TCP (传输控制协议) - rfc793 连接模式的传输。 保证按顺序传送数据包。 流量控制、错误检测和在数据包丢失时的重传。 用于需要可靠传输的应用,如网络(HTTP/HTTPS)、电子邮件(SMTP, IMAP, POP3)…

Mybatis 动态SQL条件查询(注释和XML方式都有)

需求 : 根据用户的输入情况进行条件查询 新建了一个 userInfo2Mapper 接口,然后写下如下代码,声明 selectByCondition 这个方法 package com.example.mybatisdemo.mapper; import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*; import j…

跟着我学Python进阶篇:03. 面向对象(下)

往期文章 跟着我学Python基础篇:01.初露端倪 跟着我学Python基础篇:02.数字与字符串编程 跟着我学Python基础篇:03.选择结构 跟着我学Python基础篇:04.循环 跟着我学Python基础篇:05.函数 跟着我学Python基础篇&#…

Django框架二

一、模型层及ORM 1.模型层定义 负责跟数据库之间进行通信 2.Django配置mysql 安装mysqlclient,mysqlclient版本最好在13.13以上 pip3 install mysqlclient DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: "mysite1",USER:root,PASSWO…

U-Boot 中使用 nfs 命令加载文件报错指南

目录 问题一问题描述错误原因解决方案 问题二问题描述解决方案 更多内容 在嵌入式 Linux 开发中,我们经常使用 nfs 命令加载服务端的共享文件或者挂载文件系统。关于服务端 NFS 服务的搭建可以参考基于 NFS 的文件共享实现。 U-Boot 也支持了 nfs 命令,…

JRT和springboot比较测试

想要战胜他,必先理解他。这两天系统的学习Maven和跑springboot工程,从以前只是看着复杂,现在到亲手体验一下,亲自实践的才是更可靠的了解。 第一就是首先Maven侵入代码结构,代码一般要按约定搞src/main/java。如果是能…

2526. 随机数生成器(BSGS,推导)

题目路径: https://www.acwing.com/problem/content/2528/ 思路:

【UEFI基础】EDK网络框架(MTFTP4)

MTFTP4 在TCP/IP网络协议族中有FTP协议,但是UEFI下的MTFTP4并不是对FTP协议的实现,两者虽然功能上差不多,但是实现却是不同的。FTP下层使用TCP来连接: 而MTFTP4下层却是UDP4。 MTFTP4代码综述 MTFTP4的实现在NetworkPkg\Mtftp4…

【数据结构】在链队列中你可能忽视的二三事

链队列及其基本操作的C语言实现 导言一、链队列二、链队列的基本操作的实现2.1 链队列的数据类型2.2 链队列的初始化2.2.1 带头结点的链队列的初始化2.2.3 不带头结点的链队列的初始化 2.3 链队列的判空2.3.1 带头结点的链队列的判空2.3.2 不带头结点的链队列的判空 2.4 链队列…

数据集笔记:UJIIndoorLoc

1 数据集介绍 UJIIndoorLoc - UCI Machine Learning Repository UJIIndoorLoc是一个多建筑多楼层的室内定位数据库,用于测试依赖于WLAN/WiFi指纹的室内定位系统。 2 数据读取 数据分类训练数据和测试数据 import pandas as pdapd.read_csv(Downloads/ujiindoo…