电商参考架构第二部分:库存优化方法

标签: 数据库 电商架构 mongodb | 发表时间:2015-07-14 20:58 | 作者:Mongoing中文社区
出处:http://segmentfault.com/blogs

本文源地址: http://www.mongoing.com/blog/retail-reference-architecture-part-2-appr...


在电商参考架构系列的第一部分中,我们介绍了一个大数据量电商如何使用MongoDB作为一个庞大产品目录持久层的一些最佳实践。第一部分中包括了索引、模式以及查询优化以保证我们的目录能够支持类似于搜索、单店价格以及在高效率方式下多方面检索及浏览等特性。在接下来的两篇博客中,我们将介绍相似类型的优化方法,并且将其应用到一个电商业务中完全不同的方面——库存。

一个可以通过电商的店铺及应用访问到的、可靠的、集中的库存系统是提高和丰富用户体验中一个非常庞大的基础部分。下面列举了一个电商或许想要得到的一些特性:

  • 可靠地检查产品的实时库存
  • 提供用户在某个指定实体店提货的选项
  • 在某个商品有促销的情况下,判断每日补给的需求

库存系统的问题

上面这些都是一些看似基础的特性,但是实际上也是目前大多数电商普遍使用的传统库存系统类型所面临的真实问题。在这些系统中,单个店铺维护他们各自的库存,然后在某个特定的时间间隔之后(通常是晚上)将数据返回关系型数据库管理系统中心。接着,关系型数据库管理系统将当天接收到的所有数据整合和分类之后,用于分析、报表等操作,并且将其提供给外部及内部应用。在关系型数据库管理系统和其它应用之间,通常会有一个缓存层,因为在很多情况下,关系型数据库并不是很适合处理该客户端请求的事务数量,特别是面向用户的移动或者网页应用。

因此,现在的问题非常清晰了。这些系统基础的创建并不适用于针对我们拥有多少库存以及库存位置提供一个连续精确的映射关系。此外,还可能带来维护多个系统而导致的复杂性上升的情况,例如:缓存以及持久性等等。而MongoDB则是对这些场景的最好选择 -即使在电商店铺在地理上分布很散,MongoDB仍然可以实现到产品信息的高精确度和系统的高可靠性。

设计原则

首先,我们确定好在电商参考架构中的库存系统应该要做的事情:

  • 提供一个库存的360°视图,可以在任何时间被任何客户端访问
  • 能够被任何需要库存数据的系统使用
  • 解决大数据量、以读取为主的工作负载,例如:库存检查
  • 解决大数据量的实时写操作,例如:库存更新
  • 支持批量写入操作以更新系统记录
  • 地理上分离
  • 伴随着库存中店铺数量或者商品数量的增多,保持水平扩展

简而言之,我们需要的是构建一个高性能、可水平扩展的系统,在一个庞大的、地理分布的区域中的店铺和用户都能够与MongoDB进行实时交互来查看和更新目录。

店铺模式

用户案例的一个基本需求是为每个店铺维护一个关于所有库存的、集中的、实时的视图。我们首先需要为店铺集合创建视图,从而将我们的库存与地理位置相联系起来。结果是:每个店铺都使用一个相当直接的文档。

  {

“_id”:ObjectId(“78s89453d8chw28h428f2423”),

“className”:”catalog.Store”,

“storeId”:”store100”,

“name”:”Bessemer Store”,

“address”:{

“addr1”:”1 Main St.”,

“city”:”Bessemer”,

“state”:”AL”,

“zip”:”12345”,

“country”:”USA”

},

“location”:[-86.95444, 33.40178],

…

}

然后,我们可以创建下列的索引来优化在店铺数据中最经常使用读取类型:

  • {“storeId”:1},{“unique”:true}: 获取某个特定商店的库存
  • {“name”:1}:根据名字获取商店名称
  • {“address.zip”:1}: 获取一个邮编内的所有店铺,例如:店铺定位程序
    - {“location”: 2dsphere}:获取某一个特定地理位置周围的所有商店

在上面所有的索引中,位置索引对我们来说非常有用,因为它允许我们基于某个位置近似查询商店。例如,一个用户寻找某个产品有现货的最近商店。为了在分片环境中利用这个优势,我们使用一条geoNear的命令来检索得到那些“位置”属性在给定点一定距离之内的文档,然后对最近的店铺进行排序:

  db.runCommand({
geoNear:“stores”,
near:{
type:”Point”,
coordinates:[-82.8006,40.0908], //GeoJSON or coordinate pair
maxDistance:10000.0, //in meters
spherical:true //required for 2dsphere indexes
}
})

这种模式给了我们定位对象的能力,但是同时也给在这些店铺中追踪和管理库存带来了更大的挑战。

库存数据模型

既然我们已经将商品和店铺联系了起来,我们需要创建一个库存集合来跟踪每一个商品以及它们所有商品系列的真实库存量。然而,我们需要在其中进行一定的取舍。为了同时最小化对数据库的来回读取数目,同时降低应用级的连接,我们决定将数据从店铺集合复制到库存集合。我们提出的文档是这样的:

  {
“_id”:”902372093572409542jbf42r2f2432”,
“storeId”:”store100”,
“location”:[-86.95444, 33.40178],
“productId”:”20034”,
“vars”:[
{“sku”:”sku1”, “quantity”:”5”},
{“sku”:”sku2”, “quantity”:”23”},
{“sku”:”sku3”, “quantity”:”2”},
…
]
}

首先注意到:我们在库存文档中同时包括了 storeIdlocation属性。很明显, storeId对于我们知道哪个商店有什么商品是非常必要的,但是——当我们查询离用户附近的库存时会发生什么呢?需要同时使用到库存数据以及店铺位置数据才能完成这个请求。通过在库存文档中添加地理位置数据,我们消除了在店铺集合中执行一个单独查询的需求,也减少了店铺集合和库存集合的一个连接操作。

此外,在我们的模式中,我们还决定在商品级别文档中表示库存。正如我们在电商参考架构系列第一部分中提到的,每个产品可能会拥有成百上千的商品系列/型号,包括尺寸、颜色、风格等等,所有这些系列必须在我们的库存中表示出来。那么,问题就是:我们是否应该支持包含一个更大系列集合的更大文档,还是在具体商品型号上表示库存的更多文档呢?在这种情况下,我们比较倾向于更大的文档以降低数据冗余度,这样做也可以减少在库存集合中需要查询或者更新的文档总数。

接下来,我们创建索引:

  • {storeId:1}: 得到某一个指定商店库存中的所有商品
  • {productId:1},{storeId:1}: 获取一个指定店铺中某个产品的库存
  • {productId:1},{location:”2dsphere”}:获取在一定距离之内的某个产品的所有库存

值得注意的是:我们并没有选择创建一个包含 vars.sku 的索引。没有这样做的原因是:这并不会给我们带来非常多的好处,因为我们已经可以基于 productID查询我们的库存了:

  db.inventory.find(
{
“storeId”:”store100”,
“productId”:“20034”,
“vars.sku”:”sku11736”
},
{“vars.$”:1}
)

实际上,我们并不会从 vars.sku索引上受益多少。在这种情况下,在 productID上的索引已经可以得到文档了,因此在该变量上的索引是不必要的。此外,由于系列数组有可能有成千上万的条目,在上面的索引可能会占用一大块内存,从而减少在内存中存储的文档数目,这就意味着会降低查询速度。考虑所有的事情,在给定目标的前提下,这是一个不中意的取舍。

那么是什么使得我们的模式如此合适呢?我们将在下一篇博客中讨论这个方法为库存系统提供的一些特色。

了解更多

为了进一步了解如何使用MongoDB重新开启你的零售商之旅,请阅读我们的白皮书。在这篇文章中,你将会了解新的零售挑战以及MongoDB如何解决它们。

本文译自: https://www.mongodb.com/blog/post/retail-reference-architecture-part-2...

翻译:周颖敏
审稿:TJ

阅读第一部分

快速启动你的应用

相关 [电商 参考 架构] 推荐:

电商参考架构第二部分:库存优化方法

- - SegmentFault 最新的文章
在电商参考架构系列的第一部分中,我们介绍了一个大数据量电商如何使用MongoDB作为一个庞大产品目录持久层的一些最佳实践. 第一部分中包括了索引、模式以及查询优化以保证我们的目录能够支持类似于搜索、单店价格以及在高效率方式下多方面检索及浏览等特性. 在接下来的两篇博客中,我们将介绍相似类型的优化方法,并且将其应用到一个电商业务中完全不同的方面——库存.

[译] 架构师经常参考的 Netflix 架构,它的全貌是怎样的?

- - IT瘾-dev
导读:在架构讨论中,我们碰到的问题常常会落到一些经典的架构模式中,而 Netflix 提供了几乎各种模式的参考范例. 因此了解 Netflix 架构全貌可以帮助我们进一步体系性的了解互联网架构. 本文由高可用架构翻译,转载请注明出处. 随着我们深入研究可扩展架构,我们越来越多的接触到 Netflix.

Eucalyptus私有云 -- 参考架构(小型开发测试云)

- - 婉兮清扬
 If the target deployment is one that will need to scale to accommodate more capacity in the future, the  Dev/Test (Large) reference architecture should be used, instead.

从小型网站到超大规模网站的MySQL参考架构

- - 互联网旁观者
Oracle发布《 面向大规模可伸缩网站基础设施的MySQL参考架构》白皮书,针对将MySQL用作数据存储的不同类型和不同规模的网站给出了推荐的拓扑结构. 根据分别提供4类服务——用户和会话管理、电子商务、分析类应用 (多结构数据)和CMS(元数据)——的网站的规模和可用性要求(如下表所示),这份白皮书给出了4个参考架构.

海尔电商峰值系统架构设计最佳实践

- - 博客园_知识库
  多数电商平台都会经历相似的过程,流量和业绩每年以几倍至十几倍的速度增长,每年都要接受几次大规模、全方位的系统检阅,例如双11、周年庆等购物狂欢节,期间流量和订单可能是日常的十几倍甚至几十倍,产生的峰值对平台形成极其强烈的冲击,对电商平台的架构带来巨大的考验. 因此,对电商平台的规划和架构工作不仅要高瞻远瞩,而且要细致入微,否则将导致平台无法满足高速增长的业务发展,细微处的失误也可能造成严重后果,不仅影响业务指标的实现,还可能导致对系统进行重新架构,劳时费力又伤钱.

电商搜索引擎的架构设计和性能优化

- - SegmentFault 最新的文章
「 OneAPM 技术公开课」由应用性能管理第一品牌. OneAPM 发起,内容面向 IT 开发和运维人员. 云集技术牛人、知名架构师、实践专家共同探讨技术热点. 本文系「OneAPM 技术公开课」第一期演讲嘉宾前当当网高级架构师吴英昊的演讲整理:. 首先,非常感谢 OneAPM 技术公开课举办的这次活动.

基于用户画像大数据的电商防刷架构

- - 快课网
最近1~2年电商行业飞速发展,各种创业公司犹如雨后春笋大量涌现,商家通过各种活动形式的补贴来获取用户、培养用户的消费习惯. 但任何一件事情都具有两面性,高额的补贴、优惠同时了也催生了“羊毛党”. “羊毛党”的行为距离欺诈只有一步之遥,他们的存在严重破环了活动的目的,侵占了活动的资源,使得正常的用户享受不到活动的直接好处.

基于大中台小前台模式设计高并发电商架构

- -
什么是大中台(业务中台、数据中台、技术中台等). 大中台小前台的组织模式最近在业界很火热,此模式最早在芬兰著名移动游戏公司Supercell实施. 在Supercell公司内部以小前台的方式组织了若干个开发团队,每个开发团队包含开发一款游戏所需的各种角色,从而在开发团队内部可以快速决策、快速开发. 而支撑这些开发团队的基础设施(机房、网络、架构组件等)、游戏引擎、内部开发测试发布上线工具等则由“部落”(即中台)部门提供.

Solr调优参考

- - 淘宝网通用产品团队博客
共整理三部分,第一部分Solr常规处理,第二部分针对性性处理,前者比较通用,后者有局限性. 务必根据具体应用特性,具体调节参数,对比性能. 具体应用需要全面去把控,各个因素一起起作用. 第一部分. E文连接 http://wiki.apache.org/solr/SolrPerformanceFactors.

架构

- - IT瘾-dev
网关:Nginx、Kong、Zuul. 缓存:Redis、MemCached、OsCache、EhCache. 搜索:ElasticSearch、Solr. 熔断:Hystrix、resilience4j. 负载均衡:DNS、F5、LVS、Nginx、OpenResty、HAproxy. 注册中心:Eureka、Zookeeper、Redis、Etcd、Consul.