花都营销型网站建设,百度搜索引擎关键词优化,如何做点击赚钱的网站,大型网站设计如果在业务架构设计初期#xff0c;表结构没有设计好#xff0c;那么后期随着业务以及数据量的增多#xff0c;系统就很容易出现瓶颈。如果表结构扩展性差#xff0c;业务耦合度将会越来越高#xff0c;系统的复杂度也将随之增加。这一讲我将以电商系统中的表结构设计为例…如果在业务架构设计初期表结构没有设计好那么后期随着业务以及数据量的增多系统就很容易出现瓶颈。如果表结构扩展性差业务耦合度将会越来越高系统的复杂度也将随之增加。这一讲我将以电商系统中的表结构设计为例为你详讲解在设计表时我们都需要考虑哪些因素又是如何通过表设计来优化系统性能。
1、核心业务
要懂得一个电商系统的表结构设计我们必须先得熟悉一个电商系统中都有哪些基本核心业务。这部分的内容只要你有过网购经历就很好理解。
一般电商系统分为平台型和自营型电商系统。平台型电商系统是指有第三方商家入驻的电商平台第三方商家自己开设店铺来维护商品信息、库存信息、促销活动、客服售后等典型的代表有淘宝、天猫等。而自营型电商系统则是指没有第三方商家入驻而是公司自己运营的电商平台常见的有京东自营、苹果商城等。
两种类型的电商系统比较明显的区别是卖家是 C 端还是 B 端很显然平台型电商系统的复杂度要远远高于自营型电商系统。为了更容易理解商城的业务我们将基于自营型电商系统来讨论表结构设计优化这里以苹果商城为例。
一个电商系统的核心业务肯定就是销售商品了围绕销售商品我们可以将核心业务分为以下几个主要模块
1.1、商品模块
商品模块主要包括商品分类以及商品信息管理商品分类则是我们常见的大分类了有人喜欢将分类细化为多个层级例如第一个大类是手机、电视、配件等配件的第二个大类又分为耳机、充电宝等。为了降低用户学习系统操作的成本我们应该尽量将层级减少。
当我们通过了分类查询之后就到了商品页面一个商品 Item 包含了若干商品 SKU。商品 Item 是指一种商品例如 IPhone9就是一个 Item商品 SKU 则是指具体属性的商品例如金色 128G 内存的 IPhone9。
1.2、购物车模块
购物车主要是用于用户临时存放欲购买的商品并可以在购物车中统一下单结算。购物车一般分为离线购物车和在线购物车。离线购物车则是用户选择放入到购物车的商品只保存在本地缓存中在线购物车则是会同步这些商品信息到服务端。
目前大部分商城都是支持两种状态的购物车当用户没有登录商城时主要是离线购物车在记录用户的商品信息当用户登录商城之后用户放入到购物车中的商品都会同步到服务端以后在手机和电脑等不同平台以及不同时间都能查看到自己放入购物车的商品。
1.3、订单模块
订单是盘活整个商城的核心功能模块如果没有订单的产出平台将难以维持下去。订单模块管理着用户在平台的交易记录是用户和商家交流购买商品状态的渠道用户可以随时更改一个订单的状态商家则必须按照业务流程及时订单的更新状态告知用户已购买商品的具体状态。
通常一个订单分为以下几个状态待付款、待发货、待收货、待评价、交易完成、用户取消、仅退款、退货退款状态。一个订单的流程见下图 1.4、库存模块
这里主要记录的是商品 SKU 的具体库存信息主要功能包括库存交易、库存管理。库存交易是指用户购买商品时实时消费库存库存管理主要包括运营人员对商品的生产或采购入库、调拨。
一般库存信息分为商品 SKU、仓区、实时库存、锁定库存、待退货库存、活动库存。
现在大部分电商都实现了华南华北的库存分区所以可能存在同一个商品 SKU 在华北没有库存而在华南存在库存的情况所以我们需要有仓区这个字段用来区分不同地区仓库的同一个商品 SKU。
实时库存则是指商品的实时库存锁定库存则表示用户已经提交订单到实际扣除库存或订单失效的这段时间里锁定的库存待退货库存、活动库存则分别表表示订单退款时的库存数量以及每次活动时的库存数量。
除了这些库存信息我们还可以为商品设置库存状态例如虚拟库存状态、实物库存状态。如果一个商品不需要设定库存可以任由用户购买我们则不需要在每次用户购买商品时都去查询库存、扣除库存只需要设定商品的库存状态为虚拟库存即可。
1.5、促销活动模块
促销活动模块是指消费券、红包以及满减等促销功能这里主要包括了活动管理和交易管理。前者主要负责管理每次发放的消费券及红包有效期、金额、满足条件、数量等信息后者则主要负责管理用户领取红包、消费券等信息。
2、业务难点
了解了以上那些主要模块的具体业务之后我们就可以更深入地去评估从业务落实到系统实现可能存在的难点以及性能瓶颈了。
2.1、不同商品类别存在差异如何设计商品表结构
我们知道一个手机商品的详细信息跟一件衣服的详细信息差别很大手机的 SKU 包括了颜色、运行内存、存储内存等而一件衣服则包含了尺码、颜色。
如果我们需要将这些商品都存放在一张表中要么就使用相同字段来存储不同的信息要么就新增字段来维护各自的信息。前者会导致程序设计复杂化、表宽度大从而减少磁盘单页存储行数影响查询性能且维护成本高后者则会导致一张表中字段过多如果有新的商品类型出现又需要动态添加字段。
比较好的方式是通过一个公共表字段来存储一些具有共性的字段创建单独的商品类型表例如手机商品一个表、服饰商品一个表。但这种方式也有缺点那就是可能会导致表非常多查询商品信息的时候不够灵活不好实现全文搜索。
这时候我们可以基于一个公共表来存储商品的公共信息同时结合搜索引擎将商品详细信息存储到键值对数据库例如 ElasticSearch、Solr 中。
2.2、双十一购物车商品数量大增购物车系统出现性能瓶颈怎么办
在用户没有登录系统的情况下我们是通过 cookie 来保存购物车的商品信息而在用户登录系统之后购物车的信息会保存到数据库中。
在双十一期间大部分用户都会提前将商品加入到购物车中在加入商品到购物车的这段操作中由于时间比较长操作会比较分散所以对数据库的写入并不会造成太大的压力。但在购买时由于多数属于抢购商品用户对购物车的访问则会比较集中了如果都去数据库中读取那么数据库的压力就可想而知了。
此时我们应该考虑冷热数据方案来存储购物车的商品信息用户一般都会首选最近放入购物车的商品这些商品信息则是热数据而较久之前放入购物车中的商品信息则是冷数据我们需要提前将热数据存放在 Redis 缓存中以便提高系统在活动期间的并发性能。例如可以将购物车中近一个月的商品信息都存放到 Redis 中且至少为一个分页的信息。
当在缓存中没有查找到购物车信息时再去数据库中查询这样就可以大大降低数据库的压力。
2.3、订单表海量数据如何设计订单表结构
通常我们的订单表是系统数据累计最快的一张表无论订单是否真正付款只要订单提交了就会在订单表中创建订单。如果公司的业务发展非常迅速那么订单表的分表分库就只是迟早的事儿了。
在没有分表之前订单的主键 ID 都是自增的并且关联了一些其它业务表。一旦要进行分表分库就会存在主键 ID 与业务耦合的情况而且分表后新自增 ID 与之前的 ID 也可能会发生冲突后期做表升级的时候我们将会面临巨大的工作量。如果我们确定后期做表升级建议提前使用 snowflake 来生成主键 ID。
如果订单表要实现水平分表那我们基于哪个字段来实现分表呢
通常我们是通过计算用户 ID 字段的 Hash 值来实现订单的分表这种方式可以优化用户购买端对订单的操作性能。如果我们需要对订单表进行水平分库那就还是基于用户 ID 字段来实现。
在分表分库之后对于我们的后台订单管理系统来说查询订单就是一个挑战了。通常后台都是根据订单状态、创建订单时间进行查询的且需要支持分页查询以及部分字段的 JOIN 查询如果需要在分表分库的情况下进行这些操作无疑是一个巨大的挑战了。
对于 JOIN 查询我们一般可以通过冗余一些不常修改的配置表来实现。例如商品的基础信息我们录入之后很少修改可以在每个分库中冗余该表如果字段信息比较少我们可以直接在订单表中冗余这些字段。
而对于分页查询通常我们建议冗余订单信息到大数据中。后台管理系统通过大数据来查询订单信息用户在提交订单并且付款之后后台将会同步这条订单到大数据。用户在 C 端修改或运营人员在后台修改订单时会通过异步方式通知大数据更新该订单数据这种方式可以解决分表分库后带来的分页查询问题。
2.4、抢购业务如何解决库存表的性能瓶颈
在平时购买商品时我们一般是直接去数据库检查、锁定库存但如果是在促销活动期间抢购商品我们还是直接去数据库检查、更新库存的话面对高并发系统无疑会产生性能瓶颈。
一般我们会将促销活动的库存更新到缓存中通过缓存来查询商品的实时库存并且通过分布式锁来实现库存扣减、锁定库存。
2.5、促销活动也存在抢购场景如何设计表
促销活动中的优惠券和红包交易很多时候跟抢购活动有些类似。
在一些大型促销活动之前我们一般都会定时发放各种商品的优惠券和红包用户需要点击领取才能使用。所以在一定数量的优惠券和红包放出的同时也会存在同一时间抢购这些优惠券和红包的情况特别是一些热销商品。
我们可以参考库存的优化设计方式使用缓存和分布式锁来查询、更新优惠券和红包的数量通过缓存获取数量成功以后再通过异步方式更新数据库中优惠券和红包的数量。
3、总结
这一讲我们结合电商系统实战练习了如何进行表设计可以总结为以下几个要点
在字段比较复杂、易变动、不方便统一的情况下建议使用键值对来代替关系数据库表存储在高并发情况下的查询操作可以使用缓存代替数据库操作提高并发性能数据量叠加比较快的表需要考虑水平分表或分库避免单表操作的性能瓶颈除此之外我们应该通过一些优化尽量避免比较复杂的 JOIN 查询操作例如冗余一些字段减少 JOIN 查询创建一些中间表减少 JOIN 查询。
4、思考题
你在设计表时是否使用过外键来关联各个表呢目前互联网公司一般建议逻辑上实现各个表之间的关联而不建议使用外键来实现实际的表关联你知道这为什么吗