基于TableStore的海量电商订单元数据管理

摘要: # 一、背景 订单系统存在于各行各业,如电商订单、银行流水、运营商话费账单等,是一个非常广泛、通用的系统。对于这类系统,在过去十几年发展中已经形成了经典的做法。但是随着互联网的发展,以及各企业对数据的重视,需要存储和持久化的订单量越来越大。

一、背景
订单系统存在于各行各业,如电商订单、银行流水、运营商话费账单等,是一个非常广泛、通用的系统。对于这类系统,在过去十几年发展中已经形成了经典的做法。但是随着互联网的发展,以及各企业对数据的重视,需要存储和持久化的订单量越来越大。数据的重视程度与数据规模的膨胀带来了新的挑战,原有的系统是否还能继续满足需求成了焦点?

需求场景
某电商平台A,需要进行持久化所有平台产生的订单数据。同时,基于所有的订单数据,系统又需要向外提供面向多种角色:消费者、店家、平台三类人群的多元化的查询服务。消费者可以查询自己的历史订单,商家可以统计热销产品,平台也可以分析用户行为、平台交易规模等。主要查询方式涵盖订单的多维度检索,以及订单数据的分析、统计等,例如:
面向消费者:【A消费者】【近1年】【产品名含‘电脑‘字段】订单查询;
面向店家:【B店家】【近1个月】【每个产品】销售量排名;
......

技术点
在订单场景中,技术上通常需要考虑的技术点,主要包含如下几个方面:

查询能力:需要具备丰富的查询类型,如多维度、范围、模糊查询等,同时具备排序、统计等功能;
数据量:存储海量数据的同时,满足强一致、高可用、低成本等要求;
服务性能:应对高并发请求高并发的同时,保证低延迟;
二、方案演进
应对订单场景,电商通常会采用MySQL传统方案。借助关系型数据库强大的查询能力,用户可直接通过SQL语句实现订单数据的多维度查询、数据统计等。所谓数据膨胀,分为横向、纵向两种,横向即不断迭代引入的新字段维度,纵向即总的存储数据量。在面对这两种订单数据膨胀上,单MySql方案逐渐变得吃力。 SQL + NoSQL的组合方案(以下称:组合方案)便应运而生,借助两个数据库各自的优势分别解决不同场景各自的需求。但组合方案同样也带来了新的问题,组合方案牺牲空间成本,同时也增加了开发工作量与运维复杂度。在保证数据一致性上产生额外开销。

下面让我们看一下如下几个常规方案:

常规方案
1、MySql分库分表方案
MySql自身拥有强大的数据查询、分析功能,基于MyQql创建订单系统,可以应对订单数据多维查询、统计场景。伴随着订单数据量的增加,用户会采取分库、分表方案应对,通过这种伪分布式方案,解决数据膨胀带来的问题。但数据一旦达到瓶颈,便需要重新创建更大规模的分库+数据的全量迁移,麻烦就会不断出现。数据迭代、膨胀带来的困扰,是MySql方案难于逾越的。仅仅依靠MySql的传统订单方案短板凸显。
1、数据纵向(数据规模)膨胀:采用分库分表方案,MySql在部署时需要预估分库规模,数据量一旦达到上限后,重新部署并做数据全量迁移;
2、数据横向(字段维度)膨胀:schema需预定义,迭代新增新字段变更复杂。而维度到达一定量后影响数据库性能;

2、MySql+HBase方案
引入双数据的方案应运而生,通过实时数据、历史数据分存的方案,可以一定程度解决数据量膨胀问题。该方案将数据归类成两部分存储:实时数据、历史数据。同时通过数据同步服务,将过期数据同步至历史数据。
1、实时订单数据(例如:近3个月的订单):将实时订单存入MySql数据库。实时订单的总量膨胀的速度得到了限制,同时保证了实时数据的多维查询、分析能力;
2、历史订单数据(例如:3个月以前的订单):将历史订单数据存入HBase,借助于HBase这一分布式NoSql数据库,有效应对了订单数据膨胀困扰。也保证了历史订单数据的持久化;
但是,该方案牺牲了历史订单数据对用户、商家、平台的使用价值,假设了历史数据的需求频率极低。但是一旦有需求,便需要全表扫描,查询速度慢、IO成本很高。而维护数据同步又带来了数据一致性、同步运维成本飙升等难题;

3、MySql+Elasticsearch方案
组合方案还有MySql+Elasticsearch,该方案同样是将数据分两部分存储,可以一定程度解决订单索引维度增长问题。用户自己维护数据同步服务,保证两部分数据的一致性;
1、全量数据:将全量的订单数据存入MySql数据库,订单ID之外的数据整体存为一个字段。该全量数据作为持久化存储,也用于非索引字段的反查;
2、查询数据:仅将需要检索的字段存入Elasticsearch(基于Lucene分布式索引数据库),借助于Elasticsearch的索引能力,提供可以应付维度膨胀的订单数据,然后必要时反查MySql获取订单完整信息;
该方案应付了数据维度膨胀带来的困扰,但是随着订单量的不断膨胀,MySql扩展性差的问题再次暴露出来。同时数据同步至Elasticsearch的方案,开发、运维成本很高,方案选择也存在弊端。

TableStore方案
如果使用表格存储(TableStore)研发的多元索引(SearchIndex)方案,则可以完美地解决以上问题。TableStore具有即开即用,按量收费等特点。多元索引随时创建,是海量电商订单元数据管理的优质方案。
TableStore作为阿里云提供的一款全托管、分布式NoSql型数据存储服务,具有【海量数据存储】、【热点数据自动分片】、【海量数据多维检索】等功能,天然地解决了订单数据大爆炸这一挑战;
同时,SearchIndex功能在保证用户数据高可用的基础上,提供了数据多维度搜索、统计等能力。针对多种场景创建多种索引,实现多种模式的检索。用户可以仅在需要的时候创建、开通索引。由TableStore来保证数据同步的一致性,这极大的降低了用户的方案设计、服务运维、代码开发等工作量。

三、基于表格存储实现的订单场景Demo
业务描述:
每成功完成一笔交易,就会生成一笔交易数据。交易数据包含了交易中的必要元素,如:交易时间、交易的双方、交易的产品、数量、价格等,这里选择最基本元素举例,仅将必要字段简历索引,格式如下:

订单持久化数据
表名:"order_table"

创建订单表
用户仅需维护一个数据库,按如下方式创建:用户可以通过控制台创建、管理Table,也可通过SDK

List<PrimaryKeySchema> primaryKey = Arrays.asList(
new PrimaryKeySchema("order_id", PrimaryKeyType.STRING)
);

TableMeta tableMeta = new TableMeta(tableName);
tableMeta.addPrimaryKeyColumns(primaryKey);
CreateTableRequest request = new CreateTableRequest(tableMeta, new TableOptions(-1, 1));
CreateTableResponse createTableResponse = otsClient.createTable(request);
创建索引
用户根据自身需求,在需要的时候随时创建索引。TableStore自动做全量、增量的索引数据同步:用户可以通过控制台创建、管理SearchIndex,也可通过SDK按如下方式创建(索引暂不支持update)

CreateSearchIndexRequest createSearchIndexRequest = new CreateSearchIndexRequest();
createSearchIndexRequest.setTableName("tableName");
createSearchIndexRequest.setIndexName("indexName");

IndexSchema indexSchema = new IndexSchema();
indexSchema.setIndexSetting(new IndexSetting(1));//必写
indexSchema.setFieldSchemas(Arrays.asList(
new FieldSchema("product_id", FieldType.KEYWORD).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("product_name", FieldType.TEXT).setIndex(true),//TEXT不能设置docValues
new FieldSchema("product_type", FieldType.KEYWORD).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("product_count", FieldType.DOUBLE).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("consumer_id", FieldType.KEYWORD).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("seller_id", FieldType.KEYWORD).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("total_pay", FieldType.DOUBLE).setIndex(true).setEnableSortAndAgg(true).setStore(true),
new FieldSchema("time_stamp", FieldType.LONG).setIndex(true).setEnableSortAndAgg(true).setStore(true)
));
createSearchIndexRequest.setIndexSchema(indexSchema);

CreateSearchIndexResponse createSearchIndexResponse = otsClient.createSearchIndex(createSearchIndexRequest);
数据读取
数据读取分为两类:
1、基于原生表格存储的主键列获取:getRow, getRange, batchGetRow等;
2、基于新SearchIndex功能Query:search;

主键读取
GetRowRequest getRowRequest = new GetRowRequest();

PrimaryKey pk = new PrimaryKey(new PrimaryKeyColumn[]{
new PrimaryKeyColumn("order_id", PrimaryKeyValue.fromString("fa960b5af"))
});

SingleRowQueryCriteria singleRowQueryCriteria = new SingleRowQueryCriteria("order_table", pk);
singleRowQueryCriteria.setMaxVersions(1);
getRowRequest.setRowQueryCriteria(singleRowQueryCriteria);

GetRowResponse rowResponse = o?tsClient.getRow(getRowRequest);
Search读取
新增的search接口,通过设置QueryRequest实现不同query,不同aggregation,不同sort的功能

SearchQuery searchQuery = new SearchQuery();

//设置查询条件,用户发挥
searchQuery.setQuery(Query anyQuery);

//做分页
searchQuery.setLimit(10);
searchQuery.setOffSet(0);

SearchRequest searchRequest = new SearchRequest("tableName", "indexName", searchQuery);

SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
columnsToGet.setColumns(columnsToShow);//List<String> columnsToShow
searchRequest.setColumnsToGet(columnsToGet);

SearchResponse resp = otsClient.search(searchRequest);
返回结构

SearchResponse extends Response {
private long totalCount;//query匹配成功数据总数
private List<Row> rows;//query匹配数据列表(1)
private boolean isAllSuccess;
}
场景Demo
search功能主要分为三种:(多维度)查询,排序,聚合,使用上通过三种功能的组合来实现;

场景1:多维度查询
【"consumer_001"用户】【上个月】购买【产品名含某"牙膏"字段】的订单记录
使用:BoolQuery, TermQuery, RangeQuery, MatchPhraseQuery

BoolQuery boolQuery = new BoolQuery();

TermQuery termQuery = new TermQuery();
termQuery.setFieldName("consumer_id");
termQuery.setTerm(ColumnValue.fromString("consumer_001"));

RangeQuery rangeQuery = new RangeQuery();
rangeQuery.setFieldName("time_stamp");
rangeQuery.greaterThanOrEqual(ColumnValue.fromLong(fromTime));
rangeQuery.lessThanOrEqual(ColumnValue.fromLong(toTime));

MatchPhraseQuery matchPhraseQuery = new MatchPhraseQuery();
matchPhraseQuery.setFieldName("product_name");
matchPhraseQuery.setText("牙膏");

boolQuery.setMustQueries(Arrays.asList(
termQuery, rangeQuery, matchPhraseQuery
));

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(boolQuery);
searchQuery.setLimit(10);

//仅构建Query
SearchRequest searchRequest = new SearchRequest("tableName", "indexName", searchQuery);
场景2:查询,排序
整个平台【上个月】【单订单支付金额】排行榜Top10
使用:RangeQuery, FieldSort

RangeQuery rangeQuery = new RangeQuery();
rangeQuery.setFieldName("time_stamp");
rangeQuery.greaterThanOrEqual(ColumnValue.fromLong(fromTime));
rangeQuery.lessThanOrEqual(ColumnValue.fromLong(toTime));

//排序因子
FieldSort fieldSort = new FieldSort("total_pay");
fieldSort.setOrder(SortOrder.DESC);

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(rangeQuery);
searchQuery.setSort(new Sort(Arrays.asList(fieldSort)));
searchQuery.setLimit(10);

//构建Query+Sort
SearchRequest searchRequest = new SearchRequest("tableName", "indexName", searchQuery);

原文链接

本文为云栖社区原创内容,未经允许不得转载。

原文地址:http://blog.51cto.com/13952056/2298366

时间: 2024-08-26 18:46:56

基于TableStore的海量电商订单元数据管理的相关文章

Java生鲜电商平台-电商订单系统全解析

Java生鲜电商平台-电商订单系统全解析 今天分享将会分为以下三个环节来阐述: 1.订单系统的介绍 2.订单系统的解构 3.垂直电商订单系统设计思路 一.什么是订单系统? 订单管理系统(OMS)是物流管理系统的一部分,通过对客户下达的订单进行管理及跟踪,动态掌握订单的进展和完成情况,提升物流过程中的作业效率,从而节省运作时间和作业成本,提高物流企业的市场竞争力.顾名思义,电商系统就是用户.平台.商户等对于订单的管控.跟踪的系统,衔接着商品中心.wms.促销系统.物流系统等,是电子商务的基础模块:

28、生鲜电商平台-库存管理设计与架构

说明:Java开源生鲜电商平台-库存管理设计与架构有以下几个功能 WMS的功能:1.业务批次管理 该功能提供完善的物料批次信息.批次管理设置.批号编码规则设置.日常业务处理.报表查询,以及库存管理等综合批次管理功能,使企业进一步完善批次管理,满足经营管理的需求. 2.保质期管理在批次管理基础上,针对物料提供保质期管理及到期存货预警,以满足食品和医yao行业的保质期管理需求.用户可以设置保质期物料名称.录入初始数据.处理日常单据,以及查询即时库存和报表等. 3.质量检验管理集成质量管理功能是与采购

原创:《Excel在零售及电商行业数据化管理中的应用》之“什么是数据化管理?

<Excel在零售及电商行业数据化管理中的应用>之“什么是数据化管理?” 各位: “随着全零售时代的到来,传统商业的每一个供应链细节都离不开数据的支撑.特别是以C端驱动的供应链模式成为主流的今天,用数字解读顾客的需求成为品牌和渠道竞争的核心.我们需要学会全面的利用数字化的方式,掌握对人.货.场.财等的经营管理.” 今天我们会从以下几个方面给大家分享”什么是数据化管理“ 1.企业大佬们,是如何看数据化管理的? 2.数据化管理的定义及Excel在数据化管理中意义: 3.数据化管理的作用及其4个层次

PHP电商订单自动确认收货redis队列

一.场景 之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的x天自动确认收货.所谓的订单自动确认收货,就是在在特定的时间,执行一条update语句,改变订单的状态. 二.思路 最笨重的做法,通过linux后台定时任务,查询符合条件的订单,然后update.最理想情况下,如果每分钟都有需要update的订单,这种方式也还行.奈何平台太小,以及卖家发货时间大部分也是密集的,不会分散在24小时的每分钟.那么,

电商系统——商品管理模型

商品管理是电商系统的核心模块之一,非常重要,下图是商品管理模块的商品物理模型图,当然实际使用时还需根据特定业务进行调整: 下面对上图中的一些表从概念上进行说明: 1. 什么是SPU与SKU SPU 全名 Standard Product Unit (标准化产品单元),它是最接近用户认知的产品单元,比如用户说,我想买个 iphone4.iphone6.小米 4,这些都是 SPU,也就是用户普遍认知范围内的一种产品.然而在电商系统中只有 SPU 并没有什么用,用户购买时肯定要确定,需要什么颜色.多少

互联网之道,看电商的数据化管理方案

关于数据化管理.我们可以将该模块的数据工作分成两个部分,一是通过数据来辅助日常工作,让日常工作中的选择判断更加规范,这是用数据来做事的.另一个是通过数据来评价工作业绩,让针对相关工作的管理更加规范,这是用数据来管理的.我们先看做事的,商品在零售电商企业中一般都走过下面的几个过程: 商品从采购开始到最终卖出去,按照商品的流程走下去,但是商品的售卖情况.退货情况又反过来影响商品的采购选择.在每个节点是有不同的事情要做(运输这个节点,很多情况运输是由供应商来负责的,所以可能零售商没什么事需要做),本篇

分布式系统电商订单号的最佳生成方式

最近在研发区块链支付系统,众所周知,有支付必有订单.今天不做支付系统的具体分析,只来谈谈目前较为热门的订单号码生成方案! 在分布式高并发情况下,订单号必须满足最重要的一个条件:唯一性,订单关系这支付明细,与支付相关的向来都是最重要的,马虎不得. 目前较为成熟的,我所知道的有两种生成方案,接下来做一下对比: 1.根据MySQL自增主键生成订单号 首先,需要创建一张满足自增条件的表,有两个字段即可,id和value,id设置为自增,类型为bigint即可 eg:在mybatis框架中 <insert

基于LNMP的简单电商网站架构

一:实验环境 centos 7 实验机 chrome 浏览器 二:实验步骤 ※注意事项 实验前,查看80端口是否被httpd服务占用,如打开,则关闭httpd服务,确保80端口未开启 1.安装必要软件 yum install mariadb mariadb-server php-fpm php php-mysql 2.下载网站源代码,解压到/data/web/下,并修改目录下所有文件的属主和属组为nobody unzip -d /data/web/ xiaomi.zip chown -R nob

电商订单ElasticSearch同步解决方案--使用logstash

一.使用logstash同步订单数据(订单表和订单项表)到ElasticSearch: 1.到官网下载logstash:https://www.elastic.co/cn/downloads/logstash 2.安装logstash前,确保需要先安装java的jdk环境 3.下载后,解压:之后千万别到bin环境点击logstash.bat这个命令启动,这样会报错的 4.接下来,在logstash安装目录找到config文件夹,在那里新增一个文件夹,我新建的为shop文件夹,然后在里面添加如下文