OTS构建SpringMVC REST风格的准实时系统

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: OTS构建SpringMVC REST风格的准实时系统

一、简介

        利用OTS为系统提供准实时系统交易流水持久化和离线批量数据存储服务。各系统的支撑系统,所有信息都会调用该服务,访问量大,存储和访问速度要求快,故服务的构建采用REST风格(SpringMVC框架天然的支持REST风格请求),对于准实时请求的响应和数据存储,采用NoSQL数据存储,即OTS。

 

        在网站访问量还不大的情况下,单个数据库完全可以应付。随着访问量的上升,几乎大部分使用MySQL架构的网站在数据库上都开始出现了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。RDS for MySQL会从主从读写分离、分库分表(DRDS)多方面解决高并发的问题。大数据量高并发环境下的MySQL应用开发越来越复杂,分表分库的规则把握都是需要经验的。虽然有像淘宝这样技术实力强大的公司开发了透明的中间件层来屏蔽开发者的复杂性,但是避免不了整个架构的复杂性。

        MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。

        而采用NoSQL可以避免如上的细节问题,NoSQL的优势:
        NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。
        NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。
        NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的web2.0时代尤其明显。

 

        阿里云表格存储(TableStore)OTS是 NoSQL 数据库的一种,提供海量 NoSQL 数据存储,支持 schemafree 的数据模型,提供单行级别的事务。服务端自动对数据进行分区和负载均衡,让单表数据从 GB 到 TB 再到 PB,访问并发从 0 至百万都无需繁琐的扩容流程,写性能在 TB 及 PB 级数据规模都能保持在单个毫秒,读性能只依赖结果数据集,而不受数据量的影响。所以相比 OLTP(联机事务处理)场景,表格存储更适用于 Web 规模级应用程序,包括社交网络、游戏、媒体共享和 IoT(物联网)、日志监控等场景。

 

 

二、框架搭建

    

1、浏览器发送rest请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<!DOCTYPE html>
< html  xmlns = "http://www.w3.org/1999/xhtml" >
<!-- Head -->
< head >
     < meta  charset = "utf-8"  />
     < title >SpringMVC - Rest</ title >
     
     < meta  name = "description"  content = "Dashboard"  />
     < meta  name = "viewport"  content = "width=device-width, initial-scale=1.0"  />
     < meta  http-equiv = "X-UA-Compatible"  content = "IE=edge"  />
     < meta  http-equiv = "Content-Type"  content = "text/html; charset=utf-8"  />
     < link  rel = "shortcut icon"  href = "assets/img/favicon.png"
         type = "image/x-icon" >
</ head >
<!-- /Head -->
<!-- Body -->
< body >
     <!-- Page Body -->
     < div  class = "page-body" >
         < div  class = "row" >
             < div  class = "col-lg-12 col-sm-12 col-xs-12" >
                 < div  class = "widget flat radius-bordered" >
                     < div  class = "widget-header bordered-bottom bordered-themeprimary" >
                         < i  class = "widget-icon fa fa-text-width" ></ i > < span
                             class = "widget-caption" >OTS构建SpringMVC REST风格的准实时系统</ span >
                         < div  class = "widget-buttons" >
                             < a  href = "#"  data-action = "refresh" > < i  class = "fa fa-undo" ></ i >
                             </ a > < a  href = "#"  data-toggle = "config" > < i  class = "fa fa-cog" ></ i >
                             </ a > < a  href = "#"  data-toggle = "maximize" > < i  class = "fa fa-expand" ></ i >
                             </ a > < a  href = "#"  data-toggle = "collapse" > < i  class = "fa fa-minus" ></ i >
                             </ a > < a  href = "#"  data-toggle = "dispose" > < i  class = "fa fa-times" ></ i >
                             </ a >
                         </ div >
                         <!--Widget Buttons-->
                     </ div >
                     <!--Widget Header-->
                     < div  class = "widget-body no-padding" >
                         < div  class = "widget-main" >
                             < table  class = "table" >
                                 < thead >
                                     < tr >
                                         < th  width = "30%" >返回类型</ th >
                                         < th >请求示例</ th >
                                     </ tr >
                                 </ thead >
                                 < tbody >
                                     < tr >
                                         < td >Web Page</ td >
                                         < td >
                                             < h5 >
                                                 查询用户name为
                                                 < a  href = "./getPageResult/许士" >许士</ a > 的记录.
                                             </ h5 >
                                             < h5 >
                                                 查询用户name为
                                                 < a  href = "./getPageResult/柯思" >柯思</ a > 的记录.
                                             </ h5 >
                                         </ td >
                                     </ tr >
                                     < tr >
                                         < td >JSON</ td >
                                         < td >
                                             < h5 >
                                                 查询用户name为
                                                 < a  href = "./getJsonResult/许士" >许士</ a > 的记录.
                                             </ h5 >
                                             < h5 >
                                                 查询用户name为
                                                 < a  href = "./getJsonResult/柯思" >柯思</ a > 的记录.
                                             </ h5 >
                                         </ td >
                                     </ tr >
                                     </ tbody >
                             </ table >
                         </ div >
                         <!--Widget Main Container-->
                     </ div >
                     <!--Widget Body-->
                 </ div >
                 <!--Widget-->
             </ div >
         </ div >
     </ div >
</ body >
<!--  /Body -->
</ html >

 

2、Controller层映射对应方法

返回界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package  com.zt.mvc.web.controller;
import  java.util.List;
import  org.springframework.stereotype.Controller;
import  org.springframework.ui.ModelMap;
import  org.springframework.web.bind.annotation.PathVariable;
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.RequestMethod;
import  com.zt.mvc.web.model.User;
import  com.zt.ots.OTSOperation;
 
@Controller
@RequestMapping ( "/getPageResult" )
class  WebController {
     
     /**
      * 查询name=传入值的OTS记录
      * @param name
      * @param model
      * @return
      */
     @RequestMapping (value =  "/{name}" , method = RequestMethod.GET)
     public  String getName( @PathVariable  String name, ModelMap model) {
         // 调用OTS查询功能
         List<User> users = OTSOperation.getRowByFilter(name);
         
         if (users !=  null  && users.size() >  0 )
             model.addAttribute( "user" , users.get( 0 ));
         else
             model.addAttribute( "user" new  User());
         return  "result" ;
     }
}

 

返回JSON:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package  com.zt.mvc.web.controller;
import  java.util.List;
import  org.slf4j.Logger;
import  org.springframework.http.HttpStatus;
import  org.springframework.http.ResponseEntity;
import  org.springframework.stereotype.Controller;
import  org.springframework.ui.ModelMap;
import  org.springframework.web.bind.annotation.ExceptionHandler;
import  org.springframework.web.bind.annotation.PathVariable;
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.RequestMethod;
import  org.springframework.web.bind.annotation.ResponseBody;
import  com.zt.mvc.web.error.ErrorHolder;
import  com.zt.mvc.web.exception.ResourceNFException;
import  com.zt.mvc.web.model.User;
import  com.zt.ots.OTSOperation;
@Controller
@RequestMapping ( "/getJsonResult" )
class  JSonController {
     
     /**
      * 根据name查询,返回user对象
      * @param name
      * @param model
      * @return
      * @throws ResourceNFException
      */
     @RequestMapping (value =  "/{name}" , method = RequestMethod.GET)
     @ResponseBody
     public  User getName( @PathVariable  String name, ModelMap model)  throws  ResourceNFException {
         System.out.println( "Name: "  + name);
         List<User> users = OTSOperation.getRowByFilter(name);
         
         if (users !=  null  && users.size() >  0 )
             return  users.get( 0 );
         else
             return  new  User();
     }
 
     @ExceptionHandler
     @ResponseBody
     public  ResponseEntity<ErrorHolder> handle(ResourceNFException e) {
         Logger logger =  null ;
         logger.warn( "The resource was not found" , e);
         return  new  ResponseEntity<ErrorHolder>( new  ErrorHolder( "The resource was not found" ),
             HttpStatus.NOT_FOUND);
     }
}

 

3、OTS过滤器查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package  com.zt.ots;
import  java.util.Iterator;
import  java.util.LinkedList;
import  java.util.List;
import  com.aliyun.openservices.ots.ClientException;
import  com.aliyun.openservices.ots.OTSClient;
import  com.aliyun.openservices.ots.OTSException;
import  com.aliyun.openservices.ots.model.ColumnValue;
import  com.aliyun.openservices.ots.model.PrimaryKeyValue;
import  com.aliyun.openservices.ots.model.RangeIteratorParameter;
import  com.aliyun.openservices.ots.model.Row;
import  com.aliyun.openservices.ots.model.RowPrimaryKey;
import  com.aliyun.openservices.ots.model.condition.RelationalCondition;
import  com.zt.mvc.web.model.User;
/**
  * @author wanglu
  * 描述:OTS 操作类
  *
  */
public  class  OTSOperation {
     private  static  final  String COLUMN_GID_NAME     =  "gid" ;
     private  static  final  String COLUMN_UID_NAME     =  "uid" ;
     private  static  final  String COLUMN_NAME_NAME    =  "name" ;
     private  static  final  String COLUMN_ADDRESS_NAME =  "address" ;
     private  static  final  String COLUMN_AGE_NAME     =  "age" ;
     private  static  final  String COLUMN_MOBILE_NAME  =  "mobile" ;
     /**
      * 使用过滤功能读取一行数据
      * @param gid
      * @param uid
      */
     public  static  List<User> getRowByFilter(String name) {
         final  String endPoint =  "http://cloud-report.cn-shanghai-zty-d01.ots.dcp.dev.ect-it.com" ;
         final  String accessId =  "<access_key_id>" ;
         final  String accessKey =  "<access_key_sceret>" ;
         final  String instanceName =  "cloud-report" ; // 仅做测试的project
         OTSClient client =  new  OTSClient(endPoint, accessId, accessKey, instanceName);
         final  String tableName =  "User_Info" ;
         try  {
             // 查询范围为:start primary key = (gid=0, INF_MIN)
             //         end primary key   = (gid=500, INF_MAX)
             // 且满足条件为:name == '方法输入name值'的所有行。
             RangeIteratorParameter param =  new  RangeIteratorParameter(tableName);
             RowPrimaryKey startPk =  new  RowPrimaryKey();
             startPk.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.fromLong( 0 ));
             startPk.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MIN);
             RowPrimaryKey endPk =  new  RowPrimaryKey();
             endPk.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.fromLong( 500 ));
             endPk.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MAX);
             param.setInclusiveStartPrimaryKey(startPk);
             param.setExclusiveEndPrimaryKey(endPk);
             RelationalCondition filter =  new  RelationalCondition(COLUMN_NAME_NAME, RelationalCondition.CompareOperator.EQUAL, ColumnValue.fromString(name));
             param.setFilter(filter);
             Iterator<Row> rowIter = client.createRangeIterator(param);
             int  totalRows =  0 ;
             List<User> result =  new  LinkedList<User>();
             User user;
             while  (rowIter.hasNext()) {
                 Row row = rowIter.next();
                 user =  new  User();
                 user.setGid(row.getColumns().get(COLUMN_GID_NAME).toString());
                 user.setUid(row.getColumns().get(COLUMN_UID_NAME).toString());
                 user.setName(row.getColumns().get(COLUMN_NAME_NAME).toString());
                 user.setAddress(row.getColumns().get(COLUMN_ADDRESS_NAME).toString());
                 user.setAge(row.getColumns().get(COLUMN_AGE_NAME).toString());
                 user.setMobile(row.getColumns().get(COLUMN_MOBILE_NAME).toString());
                 result.add(user);
                 totalRows++;
                 System.out.println(row);
             }
             System.out.println( "Total rows read: "  + totalRows);
             
             // 如果没有抛出异常,则说明成功
             System.out.println( "Get row succeeded." );
             return  result;
         catch  (ClientException ex) {
             // 如果抛出客户端异常,则说明参数等有误
             System.out.println( "Get row failed." );
         catch  (OTSException ex) {
             // 如果抛出服务器端异常,则说明请求失败
             System.out.println( "Get row failed." );
         finally  {
             client.shutdown();
         }
         
         return  null ;
     }
}

 

 

4、查询结果返回前端显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@ page language= "java"  import = "java.util.*"  pageEncoding= "UTF-8" %>
<!DOCTYPE html>
<!-- Head -->
<head>
     <meta charset= "utf-8"  />
     <title>SpringMVC - Rest</title>
     
     <meta name= "description"  content= "Dashboard"  />
     <meta name= "viewport"  content= "width=device-width, initial-scale=1.0"  />
     <meta http-equiv= "X-UA-Compatible"  content= "IE=edge"  />
     <meta http-equiv= "Content-Type"  content= "text/html; charset=utf-8"  />
     <link rel= "shortcut icon"  href= "../assets/img/favicon.png"
         type= "image/x-icon" >
</head>
<body>
     <!-- Page Body -->
     <div  class = "page-body" >
         <!-- Stacked To horizontal -->
         <h5  class = "row-title before-blue" >Rest请求结果:</h5>
         <div  class = "grid-example" >
             <div  class = "row" >
                 <div  class = "col-md-3" >Name - ${user.name}</div>
                 <div  class = "col-md-3" >Address - ${user.address}</div>
                 <div  class = "col-md-3" >Age - ${user.age}</div>
                 <div  class = "col-md-3" >Mobile - ${user.mobile}</div>
             </div>
         </div>
     </div>
</body>
<!--  /Body -->
</html>

 

 

三、示例运行

1、首界面

    将项目部署到Tomcat中,启动Tomcat,浏览器中输入地址:localhost:8080/rest-springmvc-ots/,回车

2、返回结果为web page的请求

    在返回类型为web page中,点击‘许士’超链接,经过OTS准实时查询,观察到浏览器的链接变为:localhost:8080/rest-springmvc-ots/getPageResult/许士,该rest请求表示发送查询name为‘许士’的请求,返回OTS准实时查询结果。当然,不过不通过超链接,直接在浏览器窗口输入rest请求localhost:8080/rest-springmvc-ots/getPageResult/许士,也是可以的。

    再如,查询name为‘柯思’的记录:localhost:8080/rest-springmvc-ots/getPageResult/柯思

 

3、返回结果为json的请求

    在返回类型为json时,点击首页中的超链接,或者发送rest请求,即可得到OTS返回结果为JSON格式的结果:localhost:8080/rest-springmvc-ots/getJsonResult/许士:

    再如,查询name为‘柯思’的记录:localhost:8080/rest-springmvc-ots/getJsonResult/柯思

 

 

四、开发建议

     开发参考:OTS 开发参考 Git:https://github.com/aliyun/aliyun-tablestore-java-sdk

     开发参考:SpringMVC REST开发参考:http://jinnianshilongnian.iteye.com/blog/1996071

     使用参考:Gogs:https://www.oschina.net/p/gogs

相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
阿里云表格存储使用教程
表格存储(Table Store)是构建在阿里云飞天分布式系统之上的分布式NoSQL数据存储服务,根据99.99%的高可用以及11个9的数据可靠性的标准设计。表格存储通过数据分片和负载均衡技术,实现数据规模与访问并发上的无缝扩展,提供海量结构化数据的存储和实时访问。 产品详情:https://www.aliyun.com/product/ots
目录
相关文章
|
3月前
|
分布式计算 搜索推荐 物联网
大数据及AI典型场景实践问题之通过KafKa+OTS+MaxCompute完成物联网系统技术重构如何解决
大数据及AI典型场景实践问题之通过KafKa+OTS+MaxCompute完成物联网系统技术重构如何解决
|
存储 SQL 运维
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-架构篇
本文简要介绍了基于 MySQL 结合 Tablestore 的大规模订单系统方案。这种方案支持大数据存储、高性能数据检索、SQL搜索、实时与全量数据分析,且部署简单、运维成本低。
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-架构篇
|
存储 SQL 运维
基于Tablestore 实现大规模订单系统海量订单/日志数据分类存储的实践
前言:从最早的互联网高速发展、到移动互联网的爆发式增长,再到今天的产业互联网、物联网的快速崛起,各种各样新应用、新系统产生了众多订单类型的需求,比如电商购物订单、银行流水、运营商话费账单、外卖订单、设备信息等,产生的数据种类和数据量越来越多;其中订单系统就是一个非常广泛、通用的系统。而随着数据规模的快速增长、大数据技术的发展、运营水平的不断提高,包括数据消费的能力要求越来越高,这对支撑订单系统的数据库设计、存储系统也提出了更多的要求。在新的需求下,传统的经典架构面临着诸多挑战,需要进一步思考架构优化,以更好支撑业务发展;
762 0
基于Tablestore 实现大规模订单系统海量订单/日志数据分类存储的实践
|
存储 SQL 运维
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-架构篇
背景订单系统存在于各行各业,如电商订单、银行流水、运营商话费账单等,是一个非常广泛、通用的系统。对于这类系统,在过去十几年发展中已经形成了经典的做法。但是随着互联网的发展,以及各企业对数据的重视,需要存储和持久化的订单量越来越大,数据的重视程度与数据规模的膨胀带来了新的挑战。首先,订单量对于数据的存储、持久化、访问带来了挑战,这不仅增加了开发面对的困难,也为系统的运维带来了挑战。其次,随着大数据技
2629 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-架构篇
|
canal 存储 SQL
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据同步 DTS 篇
前言 前文架构篇,可以看到 MySQL + Tablestore 非常适合大规模订单系统这一类需求场景。那么,我们首先要做的是,利用 CDC(Change Data Capture) 技术将订单数据实时从 MySQL 同步到 Tablestore 中。对于订单系统的数据同步,我们需要关注同步的稳定性、实时性。目前,存在多款工具可以实现这一功能,他们有的是开源工具如 Canal,有的是阿里云端服务如
1071 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据同步 DTS 篇
|
canal NoSQL 关系型数据库
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据同步 Canal 篇
前言 在基于 MySQL + Tablestore 分层存储架构的大规模订单系统中,利用 CDC 技术将 MySQL 数据同步到 Tablestore 是不可缺少的一步。前文已经详细讲述了如何使用 DTS 向 Tablestore 同步数据。对于中小规模的数据库,或者个人开发者,还可以使用 Canal 从 MySQL 向 Tablestore 同步数据。Canal 部署简单,易于运维,且相比于 D
719 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据同步 Canal 篇
|
存储 SQL 运维
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-订单搜索篇
背景在大规模订单系统中,存在以下常见需求:查询某店铺过去一段时间成交额查询某品牌商品在过去一周内的成交额查询在某店铺购物的客户列表……因此,开发者对于数据库在非主键查询、多列的自由组合查询等复杂查询需求上会有比较高的要求。传统的订单系统会使用 Elasticsearch 或者 Solr 来实现这一需求,但伴随而来的是更高的系统复杂度和更加昂贵的系统维护成本。Tablestore 的多元索引,能够支
1016 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-订单搜索篇
|
SQL 存储 NoSQL
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-SQL 查询和分析
前言前面我们介绍了基于 MySQL + Tablestore 分层架构的订单系统。订单数据储存进入 Tablestore 后,用户可以使用 SDK 中的 API 访问数据,也可以继续使用 SQL 访问 Tablestore 中的数据。Tablestore 提供了多种 SQL 的接入方式,客户可以通过 DLA 访问 Tablestore,也可以利用 Tablestore 自身对 SQL 的支持能力,
956 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-SQL 查询和分析
|
存储 SQL 运维
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-基于 DLA 的联邦查询
前言在订单系统中,基于订单数据对客户和商家商品进行画像分析是一种常见的需求。常见的分析需求有:基于主键、分区键数据的条件组合检索,例如获取某用户最近 30 的订单列表。根据非主键列、分区键的条件组合检索工作,例如查询过去一天异常订单列表、查询过去一天成交额最大的10 笔订单。聚合统计类需求,比如统计某店铺过去一个月各商品销售额排名;统计双十一期间销售额前 10 的店铺;统计双十一期间某店铺每天订单
593 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-基于 DLA 的联邦查询
|
存储 SQL 分布式计算
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据处理ETL篇
前言大数据计算服务 MaxCompute(原名 ODPS)是一种快速、完全托管的EB级数据仓库解决方案。随着数据收集手段不断丰富,行业数据大量积累,数据规模已增长到了传统软件行业无法承载的海量数据(TB、PB、EB)级别。MaxCompute 致力于批量结构化数据的存储和计算,提供海量数据仓库的解决方案及分析建模服务。它具有大规模计算存储、多种计算模型、强数据安全、低成本、免运维、极致弹性扩展的优
557 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-数据处理ETL篇