15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 类淘宝千亿量级超大规模电商系统后端数据库设计实践

类淘宝千亿量级超大规模电商系统后端数据库设计实践

时间:2023-06-02 04:42:01 | 来源:网站运营

时间:2023-06-02 04:42:01 来源:网站运营

类淘宝千亿量级超大规模电商系统后端数据库设计实践:问题背景

电商网站如http://jd.comhttp://tmall.com等,订单数据一直在膨胀,每年产生个一两千亿那都是正常,要知道人家阿里11.11那天,平均每一秒钟就产生15.7w笔订单,这么算下来当天大概产生了15.7*10000*86400=13,564,800,000,嗯,135.65亿。问题:像这样超大规模订单的数据存储,如果事先没有设计好可扩展的数据架构方案和容灾方案,不久的将来肯定会抵达性能瓶颈值,成为限制业务发展的首要技术难题。


分库分表的维度选择


通常来说分库分表都是通过订单id经过简单hash算法得到一个数字hash,然后采用hash值的后五位mod|1024(32*32=1024),先对库表进行分组编号1-1024,进而得到这个订单id应该路由到那个编号的表中。当然咯,这里最好保持hash数值的后五位数能够以最大的随机性命中这1024张表中的任何一张,但出现了新的问题:这样分库分表还是无法解决若干个数据库的若干个表读写IO很高的问题

面临的几个问题


分库分表订单id如何高效生成?snowflake算法吗?不建议。分库分表的最终目的是为了服务用户,同时便于开发运维以及销售运营等系统的设计,所以我们应该以用户为主线,从user_id出发,所有与此用户(包含客户和商家)相关的订单,产品,礼品,评论,签到等一系列表都应该按照既定的原则存放在同一份库表里面,方便进行相关信息的整合查询,现在回到订单id如何生成的问题,先让新的订单表根据用户信息路由到指定的库表(例如db89_table19)中,让数据库帮我们生成一个表订单的自增id(100089),于是我们得到了订单的guid(db89_table19_order100089),当然我们写数据接口的时候肯定不能直接传这个guid,这个属于安全意识问题,因此我们使用不可逆加密算法生成对应的订单enctrypted_id(111sakhkhsa121hksajj1687971),并放入订单的全局ht_order的guid_kv(guid=>enctrypted_order_id)映射关系中。接着,引出了新的问题:某些用户表的容量已经达到了系统高性能实践所允许的阈值(假设每台机器的单表阈值是同一个常量值K),这时应该把新注册的用户数据放在哪个库对应的哪张表呢?解决办法是这样的,通过monitor服务器的来存放这些字段信息ht_load_balance(db_index,table_index,day_[read/write]_[peak|valley],month_[read/write]_[peak|valley],year_[read/write]_[peak|valley],total_count),这张表用于记录指定库指定表的负载统计情况,它统计的最小维度是day(天),接着需要把db和table的负载情况按照指定的算法进行排序(load_balance_weight_rank),然后把排序得到的权重结果缓存起来得到(load_balance_weight_rank_cache),并把排序结果更新到系统共用缓存区(同步计划的执行时间根据以往经验固定在凌晨3-5点之间执行)。

紧接着我们就可以通过这个缓存权重结果来设计新数据的库表路由选择算法,算法的设计应该尽量保证每一个数据库,乃至每一个数据库中的每一张表的的Read/Write的IO是均衡的,关于这个算法的选择思路,请小伙伴们自己发挥想象力,在此就不打算深究了。现在假设新注册一个用户,通过上面的负载均衡算法路由到了db100,table1000,然后我们把新用户的数据插入到表中得到一个自增id,接着问题来了,我们怎么知道这个用户的uid放在那张表呢?这个简单,使用hashtable来存放ht_user(guid=>enctrypted_user_id),我们看到这是最简单的kv store方式存储的,google的基于GFS的分布式bigtable来存放,这些个速度都快得没话说!于是我们把新的order_guid,product_guid,gift_guid,comment_guid都放到它们的guid_kv中,以便进行路由查询,但运营和销售又提出了新的问题。


1)运营想搞一个促销活动,打算向最近三个月购买总额超过2000元的客户推送一条促销的短信消息。好解决,分布式作业,通过制定的查询条件找到满足条件的用户手机号码,接着发送短信。

2)运营想知道销售的主要来源区域便于加强运营分析能力,当然这个也简单。

3)公司新推出了100款重点促销的商品(分布在不同的库表中),想知道这几款商品的实时销售量,点击量,这个貌似也不难。

4)接下来,难点来了,销售想知道商家的销售额排行的前100w名,该怎么办?这就有点难办了!猿哥的解决思路还是创建一个(guid=>sale_amount)kv-store,用来存储实时变更的销售额信息,离线计算。

其它诸如大数据分析,离线任务(客户端推送,短信群发等)都可以通过类似的思路解决。

系统可扩展性

通过上面的ht_load_balance负载均衡算法,我们知道了新来的用户数据应该放到那个数据库,当指定库的指定表达到最佳性能数值时(假设total_count=500w条记录,这个数值的选择可以通过一些压测模拟和生产统计手段分析得到)时,我们添加一个新的数据库服务器,并把数据库初始化的库表信息同步到ht_load_balance记录中,那么新的用户数据总是会命中新的数据库服务器,并在一定的时候达到平衡,当这个数据量快要达到临界值的时候,系统管理员,快速响应,再次部署新的服务器,从而保证服务器的扩展性。

系统的高可用性

由于极小的故障概率可能会出现的原因,通常每一台数据库服务器都会有一到多台地域彼此隔离的冷热双备服务器待命,就算其中一台出现故障,服务器节点故障侦测到异常,会马上进行切换。

本文还有几个主题

  1. 旧数据迁移原则,例如腾讯qq超过一定的年限未使用便开始冻结,甚至释放重用,而这些数据都会被迁移到旧数据服务器中存底。

  2. LRU算法,让最活跃的用户享受最快速的服务。

  3. 。。。


当然还有一些细节上的问题,限于篇幅和精力,本文就不在深究了,有兴趣的小伙伴可以自己发散思维,尽情思考,争取把这个世界架构的妙不可言。


参考文章列表:

  1. 大众点评订单系统分库分表实践:http://tech.meituan.com/dianping_order_db_sharding.html

  2. google bigtable:

    http://baike.baidu.com/item/BigTable

  3. 关于bigtable的论文:

    http://dblab.xmu.edu.cn/post/google-bigtable/

关键词:系统,数据,实践,设计,规模

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭