TiDB 助力客如云餐饮 SaaS 服务

Easter79
• 阅读 578

作者:客如云 BigData Infra Team 

公司介绍

客如云成立于 2012 年,是全球领先、 国内最大的 SaaS 系统公司。 目前面向餐饮、 零售等服务业商家, 提供软硬一体的新一代智能化前台、收银等 SaaS 云服务,包括预订、排队、外卖、点餐、收银、会员管理、进销存等系统服务,并将数据实时传达云端。我们是客如云的大数据基础架构组,负责公司的大数据架构和建设工作,为公司提供大数据基础数据服务。

业务发展遇到的痛点

  1. 随着公司业务架构越来越复杂,技术架构组需要在服务器端与应用端尽可能的通过微服务化实现业务解耦,同时需要第三方熔断服务机制来保证核心业务正常运行。数据库层面,为了保证高并发的实时写入、实时查询、实时统计分析,我们针对地做了很多工作,比如对实时要求较高的服务走缓存、对大表进行分库分表操作、对有冷热属性的大表进行归档、库分离,虽然用大量人力资源解决了部分问题,但是同时也带来了历史数据访问、跨库分表操作、多维度查询等问题。

  2. 大数据量下,MySQL 稍微复杂的查询都会很慢,线上业务也存在单一复杂接口包含执行几十次 SQL的情况,部分核心交易大库急需解决访问性能。

3. 餐饮行业有明显的业务访问高峰时间,高峰期期间数据库会出现高并发访问,而有些业务,比如收银,在高峰期出现任何 RDS 抖动都会严重影响业务和用户体验。

  1. 传统的数仓业务往往有复杂的 T+1 的 ETL 过程,无法实时的对业务变化进行动态分析和及时决策。

业务描述

大数据的 ODS(Operational Data Store) 以前选型的是 MongoDB,ODS 与支持 SaaS 服务的 RDS 进行数据同步。初期的设想是线上的复杂 SQL、分析 SQL,非核心业务 SQL 迁移到大数据的 ODS层。同时 ODS 也作为大数据的数据源,可以进行增量和全量的数据处理需求。但是由于使用的MongoDB,对业务有一定侵入,需要业务线修改相应查询语句,而这点基本上遭到业务线的同学不同程度的抵制。同时目前大数据使用的是 Hadoop + Hive 存储和访问方案,业务线需要把历史明细查询迁移到 Hadoop ,然后通过 Impala、Spark SQL、Hive SQL 进行查询,而这三个产品在并发度稍微高的情况下,响应时间都会很慢,所以大数据组在提供明细查询上就比较麻烦。 

同时更为棘手的是,面对客户查询服务(历史细则、报表等),这类查询的并发会更高,而且客户对响应时间也更为敏感,我们首先将处理后的数据(历史细则等)放在了 MongoDB 上(当时 TiDB 1.0 还没有 GA ,不然就使用 TiDB 了),然后针对 OLAP 查询使用了 Kylin ,先解决了明细查询的问题。 但是由于业务很复杂, 数据变更非常频繁,一条数据最少也会经过五六次变更操作。报表展现的不仅是当天数据,涉及到挂账、跨天营业、不结账、预定等复杂状况,生产数据的生命周期往往会超过一个月以上。所以当前的 OLAP 解决方案还有痛点,所以后续我们要把 OLAP 查询移植一部分到 TiDB 上面去,来减轻 Kylin 的压力并且支持更加灵活的查询需求,这个目前还在论证当中。 

同时,我们发现 TiDB 有一个子项目 TiSpark, TiSpark 是建立在 Spark 引擎之上,Spark 在机器学习领域里有诸如 MLlib 等诸多成熟的项目,算法工程师们使用 TiSpark 去操作 TiDB 的门槛非常低,同时也会大大提升算法工程师们的效率。我们可以使用 TiSpark 做 ETL,这样我们就能做到批处理和实时数仓,再结合 CarbonData 可以做到非常灵活的业务分析和数据支持,后期根据情况来决定是否可以把一部分 Hive 的数据放在 TiDB 上。

新老框架如下图:

TiDB 助力客如云餐饮 SaaS 服务

图:老的框架

TiDB 助力客如云餐饮 SaaS 服务

图:新的框架

TiDB 测试应用

1. 配置

阿里云服务器:

  • TiDB / PD:3 台 i1 型 机器,16c 64g ;

  • TiKV :5 台 i2 型机器,16c 128g, 1.8T*2 每台机器部署两个 KV;

  • 监控机一台。

目前我们将线上 RDS 中三个库的数据通过 Binlog 同步到 TiDB ,高峰期 QPS 23k 左右,接入了业务端部分查询服务;未来我们会将更多 RDS 库数据同步过来,并交付给更多业务组使用。因为 TiDB 是新上项目,之前的业务线也没有线上 SQL 迁移的经历,所以在写入性能上也没有历史数据对比。

TiDB 助力客如云餐饮 SaaS 服务

2. 性能对比

(1)查询一个索引后的数字列,返回 10 条记录,测试索引查询的性能。

TiDB 助力客如云餐饮 SaaS 服务

(2)查询两个索引后的数字列,返回 10 条记录(每条记录只返回 10 字节左右的 2 个小字段)的性能,这个测的是返回小数据量以及多一个查询条件对性能的影响。

TiDB 助力客如云餐饮 SaaS 服务

(3)查询一个索引后的数字列,按照另一个索引的日期字段排序(索引建立的时候是倒序,排序也是倒序),并且 Skip 100 条记录后返回 10 条记录的性能,这个测的是 Skip 和 Order 对性能的影响。

TiDB 助力客如云餐饮 SaaS 服务

(4)查询 100 条记录的性能(没有排序,没有条件),这个测的是大数据量的查询结果对性能的影响。

TiDB 助力客如云餐饮 SaaS 服务

(5)TiDB 对比 MySQL 复杂 SQL 执行速率:

  • Table 1  TiDB 数据量 5 千万,MySQL数据量 2.5 千万;

  • Table 2  TiDB 数据量 5 千万,MySQL数据量 2.5 千万;

  • Table 3  TiDB 数据量 5 千万,MySQL数据量 2.5 千万。

a. 对应 SQL:

SELECT sum(p.exempt_amount) exempt_amount FROM table1 p JOIN table2 c ONp.relate_id=c.id  AND p.is_paid = 1

andp.shop_identy in(BBBBB)  

andp.brand_identy=AAAAA

andp.is_paid=1 AND p.status_flag=1 AND p.payment_type!=8              

WHEREc.brand_identy = AAAAA

ANDc.shop_identy in(BBBBB)                              

ANDc.trade_type in(1,3,4,2,5)                          

ANDc.recycle_status=1        

AND c.trade_statusIN (4,5,10)        

ANDp.payment_time BETWEEN '2017-08-11 16:56:19' AND '2018-01-13 00:00:22'        

ANDc.status_flag = 1        

ANDc.trade_pay_status in(3,5)                    

AND c.delivery_type in(1,2,3,4,15)

TiDB 助力客如云餐饮 SaaS 服务

 b. 对应 SQL:

SELECT sum(c.sale_amount)tradeAmount,sum(c.privilege_amount) privilege_amount,sum(c.trade_amount)totalTradeAmount,sum(c.trade_amount_before) tradeAmountBefore        

FROM (SELECTc.sale_amount,c.privilege_amount,c.trade_amount,c.trade_amount_before        

FROM table1p        

JOIN table2c ON p.relate_id=c.id                                

andp.shop_identy in(BBBBB)                  

andp.brand_identy=AAAAA

andp.is_paid=1 AND p.status_flag=1 AND p.payment_type!=8              

and  c.brand_identy = AAAAA

ANDc.shop_identy in(BBBBB)                                

ANDc.trade_type in(1,3,4,2,5)                            

ANDc.recycle_status=1         AND c.trade_statusIN (4,5,10)        

ANDp.payment_time BETWEEN '2017-07-31 17:38:55' AND '2018-01-13 00:00:26'        

ANDc.status_flag = 1        

ANDc.trade_pay_status in(3,5)                      

ANDc.delivery_type in(1,2,3,4,15)                                  

ANDp.payment_type not in(4,5,6,8,9,10,11,12)        

GROUP BY p.relate_id  ) c

TiDB 助力客如云餐饮 SaaS 服务

 c. 对应 SQL:

SELECT SUM(if(pay_mode_id=-5 or pay_mode_id = -6,0,IFNULL(pi.face_amount, 0) - IFNULL(pi.useful_amount, 0) -IFNULL(pi.change_amount, 0))) redundant

FROM table2c

JOIN  table1 p ON c.id = p.relate_id AND c.brand_identy=p.brand_identy        

JOIN table3pi ON pi.payment_id=p.id AND pi.pay_status in (3,5,10)

AND  pi.brand_identy=p.brand_identy ANDpi.pay_mode_id!=-23                                

andp.shop_identy in(BBBBB)                  

andp.brand_identy=AAAAA

andp.is_paid=1 AND p.status_flag=1 AND p.payment_type!=8              

WHEREc.brand_identy = AAAAA

ANDc.shop_identy in(BBBBB)                              

ANDc.trade_type in(1,3,4,2,5)                          

ANDc.recycle_status=1        

AND c.trade_statusIN (4,5,10)        

ANDp.payment_time BETWEEN '2017-07-31 17:38:55' AND '2018-01-13 00:00:26'        

ANDc.status_flag = 1        

ANDc.trade_pay_status in(3,5)                    

AND c.delivery_type in(1,2,3,4,15)

TiDB 助力客如云餐饮 SaaS 服务

d. 对应 SQL:

SELECT  t.id tradeId,sum(t.trade_amount - t.trade_amount_before) AS roundAmount,  sum(-p.exempt_amount) AS exemptAmount

FROM table2t

LEFT JOINtable1 p ON p.relate_id = t.id

LEFT JOINtable3 pi ON pi.payment_id = p.id

WHEREt.brand_identy =AAAAA AND t.trade_status IN (4,5,10)

ANDt.trade_pay_status IN (3,4,5,6,8)  ANDp.payment_type IN (1,2)

ANDpi.pay_mode_id !=-23  ANDp.is_paid=1  AND  t.status_flag=1

AND t.shop_identy IN(<123个商户号码>)

GROUP BY t.id

TiDB 助力客如云餐饮 SaaS 服务

e. 对应 SQL:

SELECT  t.id tradeId,  

sum(t.trade_amount- t.trade_amount_before) AS roundAmount,

sum(-p.exempt_amount)AS exemptAmount

FROM table2t

 JOIN table1 p ON t.id = p.relate_id

WHERE  t.brand_identy = AAAA

ANDt.trade_status IN(4,5,10)

ANDt.trade_pay_status IN (3,4,5,6,8)  

ANDp.is_paid=1  AND  t.status_flag=1

group by t.id ;

TiDB 助力客如云餐饮 SaaS 服务

(6)OLTP 对比测试结果:

TiDB 助力客如云餐饮 SaaS 服务

TiDB 助力客如云餐饮 SaaS 服务

TiDB 助力客如云餐饮 SaaS 服务

(7)简单测试结论:

  • 不管是索引查询、分页查询、线上业务级的负载查询,大数据量下 TiDB 的性能都比 MySQL 更强;

  • TiDB 整体性能表现满足我们业务的需求。

生产使用情况

目前线上已经存储超过 6 个月的数据,总数据量几 T,支持线上的查询和分析需求,很多一般复杂度 OLAP 查询都能够在秒级返回结果。TiSpark 我们也调试通过,准备移植一些支持 OLAP 的 ETL 应用做到实时 ETL。目前 TiDB 生产还有很多优化的空间,比如系统参数,SQL 的使用姿势,索引的设计等等。

未来规划

  • 已经有一个交易量很大业务部门在向我们了解 TiDB,有可能要使用 TiDB 作为线上交易系统;

  • 后续大数据也会使用 TiSpark 来做 OLAP 查询和数据处理,同时也可能会作为 Kylin 的数据源;

  • 可以预见将来不管是 OLTP,还是 OLAP 场景,TiDB 都会在客如云发挥越来越重要的作用。

致谢

感谢 TiDB 的厂商的人员给予了我们巨大的支持,希望我们能够提供给 TiDB 一些有意义的信息和建议,在 TiDB 成长的路上添砖加瓦。

延展阅读

TiDB 在二维火餐饮管理实时报表中的实践

TiDB 在饿了么归档环境的应用

TiDB 助力一面数据实现消费领域的决策分析平台

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k