公益网站建设,张启亚学做网站,域名ip地址在线查询,给个能直接看的网址谢谢本文作者#xff1a; 振飞#xff08;高德地图总裁#xff09; 炳蔚#xff08;高德技术服务平台负责人#xff09; 福辰#xff08;高德服务端架构师#xff09; 背景 高德成立于2002年#xff0c;是中国领先的移动数字地图、导航及实时交通信息服务提供商#xff0c… 本文作者 振飞高德地图总裁 炳蔚高德技术服务平台负责人 福辰高德服务端架构师 背景 高德成立于2002年是中国领先的移动数字地图、导航及实时交通信息服务提供商向终端用户提供包括导航、本地生活、叫车等服务的一站式入口。从拥有甲级测绘资质的领先地图厂商到首家成功转型移动互联网的地理信息企业再到国民出行平台以及出门好生活开放服务平台。业务一直在进化但高德“让出行和生活更美好”的初心未变本质的核心专注点一直没有改变就是地图导航拥有从数据到软件到互联网的完整研发能力和经验同时在人工智能、大数据、计算机视觉等一系列新技能方面也拥有深厚的积累。 地图是什么它是真实物理世界在网络空间的数字化映射高德的目标就是“连接真实世界做好一张活地图”。作为如今各行各业都非常关注的一个概念“数实融合”代表大家对于实体经济进一步升级发展的期望代表着能力和效率的现象级提升以及面向用户和消费者的更优质产品和服务。而要做到这一点其中的关键在于推动实体经济和数字经济的高度融合对于高德地图所在的交通出行行业来说也是如此。我们致力于用“促科技创新、与生态共进”的方针助力交通产业更好的实现数实融合。 从高德的视角对于“数实融合”的理解是什么样的一方面我们明确了包括人、车、路、店等在内的实体要素才是交通出行产业中的真正主体相关领域中耕耘多年的企业和机构才是真正值得尊重的老师傅他们在各自领域的专业度和经验不可或缺另一方面科技创新平台提供了交通服务和海量用户之间的连接能力、数字化的展示平台提供了产业要素转化为数据的能力并且还能为各类新型交通服务提供强大的计算能力。高德的二十余年始终与大交通产业中其他领域的老师傅携手共进尊重他们的专业领域尊重他们的不可或缺才得以与他们建立起了深厚的合作关系成为他们服务的科技标配。2022年10月1日中国国庆黄金周假期的首日高德实现了创纪录的2.2亿日活跃用户。在2023年3月受到日益增长的同城通勤和城际出行需求推动高德的日均活跃用户数量达到了1.5亿的新纪录。 高德一直不断地探索和应用新的技术以持续提升用户体验、提高效率和降低成本。 首先是北斗高精度定位。作为一家科技企业高德有幸见证了北斗从起步到世界一流的发展历程。尤其是2020年的北斗三号全球组网成功客观上帮助我们在产品研发上迅速打开了新局面车道级导航、智能红绿灯、绿色出行和位置共享报平安等一系列基于北斗高精尖技术的服务得以在手机上落地并获得了行业内外的好评。如今高德地图调用北斗卫星日定位量已超过3000亿次且在定位时北斗的调用率已超越了GPS等其他卫星导航系统。 互联网地图用户高并发访问和随之而来的海量数据存储处理是我们必须应对的技术难题。其中云原生和行业无关化架构是高德地图服务端未来的努力方向。云原生是一个新的软件架构模式它将应用程序和系统环境抽象化并将它们封装到容器中以实现快速、可靠和可扩展的部署和管理云原生是未来软件架构的发展趋势它的本质是更高维度的抽象、封装和屏蔽高德地图服务端会聚焦于把云原生相关技术用到日常应用研发以提高生产力快速迭代产品跟业务一起给用户最好的体验。行业无关化架构是针对高德应用的特点提出的核心是解决研发效率的问题业务上让更多的行业快速接入高德技术上尝试元数据驱动多租户隔离屏蔽行业变化对底层的影响做到行业无关化架构以进一步提高生产力。 随着“高德地图”成为用户出行必备工具之一其中数据的存储、加密、快速检索和绝对安全就非常重要是我们工作的重点目的是让用户在任何时刻、不同的端设备上都能快速的获得自己想要的真实世界的信息让用户出行更美好。随着业务后续发展很快就会进入万亿时代无论是存储成本还是针对数据查询的性能来讲数据治理对我们来说显得尤其重要我们要让数据快速发挥出价值带给用户最真实最实时的数据还不会过度的浪费成本。 OceanBase是由蚂蚁集团完全自主研发的国产原生分布式数据库始创于2010年。OceanBase已连续10年稳定支撑双11创新推出“三地五中心”城市级容灾新标准在被誉为“数据库世界杯”的TPC-C和TPC-H测试上都刷新过世界纪录。自研一体化架构兼顾分布式架构的扩展性与集中式架构的性能优势用一套引擎同时支持OLTP和OLAP的混合负载具备数据强一致、高扩展、高可用、高性价比、高度兼容Oracle/MySQL、稳定可靠等特征不断用技术降低企业使用数据库的门槛。 经过长时间的调研和测试对比我们决定采用性价比最佳的OceanBase来迎接高德万亿条数据时代 读者收益 正因为真实世界的数据存储量大高德采用的OceanBase来解决此篇文章会让大家看到OceanBase在高德的实践体会我们会从不同的视角去诠释整篇文章。整体如下 服务端的视角 1我们为什么选择OceanBase 2OceanBase在高德落地过程中分应用的融合方案、痛点和收益 3OceanBase在高德应用中未来的规划 读者的视角 1高德为什么选择OceanBase背后选择的原因是什么 2高德怎么用OceanBase的方案是什么遇到了哪些问题解决方案是什么 3OceanBase在高德应用场景中表现结果怎么样稳定性和性能怎么样降本效果怎么样 4结合我们自己的场景哪些可以用OceanBase帮我们解题 以下用OB代替“OceanBase”整篇文章也会围绕几点来贯彻核心思想 1了解选择OceanBase的原因了解OB的落地实践 2了解分布式数据库和OB相关技术内幕 3作为工具文章在犹豫是否选择OB的时候会给大家一些思路 1.为什么选择OB 阿里云提供的数据存储产品有很多 简单罗列几个常用的(排名不分先后没写进来的不代表不好) PolarDBLindormOBESMongoDB... 每种存储都有自己的特色有关系型数据库有分布式数据库有列族数据库等在不同的场景都表现十分出色。然而我们为什么选择了OB呢 其实从21年开始我们就一直在做一个事就是去MongoDB。过去高德有一些业务服务用的MongoDB做存储由于MongoDB的特性和设计特点导致它偶尔会出现CPU占用很高服务Pause无法正常提供服务。 对于上游来说体现就是超时问题了如果访问量大且重试带来的阶梯效应就是毁灭的服务基本被打垮。很多时候不是MongoDB本身的问题它定义是分布式文档存储系统通过Documents的方式来维护数据理论上在关系型比较重的场景上确实不太适合。 后来我们服务就相继的迁移到XDB、Lindorm、ES。选择ES是因为成本低和稳定性高选择Lindorm是因为对于我们的异构场景、Key Value场景和减少请求穿透到XDB的场景非常合适。那么就剩下数据库选型了虽然OB是NewSQL数据库但是他保留了关系型数据库的特性让我们以NewSQL的方式去管理数据但不是说明任意场景都比较适合在结构化数据量大的体系中OB在降本上非常具有优势。 那么这里又有一个疑问Lindorm和ES不也可以做这种存储吗 存储和检索都非常高效。 但是从工具的角度Lindorm和ES对我们来说都是加快检索和异构检索使用的无法真正像关系型数据库那样去使用往往后面都会存在一个数据库会严重增加数据沉余和成本。 针对数据库的场景我们其实都关注两点OLTP和OLAP。PolarDB是天然的OLTP分布式MySQL引擎后续架构也支持了OLAP设计。 然而OB本身设计就是NewSQL模式天然具备OLTP和OLAP两种场景而且针对大数据有自己的压缩体系在降本和应用都有天然的优势。 1.1 OB基础属性信息 图 1.1 OB的基础属性信息 1.2 经过多方面平衡解释下我们为什么要选择OB 1OB是基于Paxos一致性协议实现的数据多副本存储(多版本并行提交)满足多数派即可返回最终一致性。 2采用无共享的多副本架构系统没有单点障碍保证系统持续可用。即使单副本出现故障也可以达到多数派可用。 3OB是可以动态扩容的扩容后分区表的数据会自动均衡到新节点上对上层业务透明节省迁移成本。 4OB存储具有高度压缩的能力数据可以压缩到原有数据到三分之一对于存储量大的业务会极大降低存储成本。 5OB作为准内存数据库采用LSM-Tree存储引擎增量数据操作内存减少随机写读写性能超传统关系型数据库而且支持Hash和BTree。 6比较重要的是OB也支持MySQL的协议可以直接使用MySQL驱动访问可以基本完全的将OB当成分布式的MySQL使用。 在布式数据库出来之前针对大数据量的读写场景广泛采用分库分表方案也由此诞生了很多分库分表、读写分离中间件。这些方案虽然能带来一定的效果也会引发一些后遗症比如 需要提前规划好分片规则一旦定好规则就难以移动扩展困难分得太细会浪费资源分得太粗会导致二次拆分数据迁移困难 说到这里大家应该还没太多体感那么我们会从分布式数据库和OB的一些技术角度去诠释上面的决策点为方便更好的做决策主要讲一些相应的分布式数据库和OB技术原理了解的同学可以直接跳过。 2. 云原生分布式数据库和OB技术内幕 2.1 云原生数据库的发展历程 云原生分布式数据库发展历程经历以下3个阶段。 单机传统单机数据库、依赖高端硬件、系统难以扩展、成本高。 PG-XC基于中间件的分布式数据库(TDDL)。待解决全局一致性、跨库事务、复杂的SQL等问题。NewSQL高可用、水平扩展、分布式事务全局一致性、复杂SQL、自动负载均衡、OLAP等。 图 2.1 数据库发展历程 (图片引自OceanBase) 3个阶段衍生出3种架构但是统一被归整为NewSQL和PG-XC的2大类风格 Sharding on MySQL一般我们可以在应用侧或者代理层做分片来管理多个MySQL物理库以解决单机容量和性能不足的问题。现在正在使用的TDDL就是该架构虽然计算存储资源可扩展但在扩展和数据迁移时业务系统层面需要做不少改造和业务数据的灰度为了保证业务不停机会产生比较大的改造成本和数据迁移的风险。(PG-XC风格) NewSQL国内以TiDB和OceanBase为代表的原生支持分布式的关系型数据库主要也是为了解决MySQL的问题。和Sharding on MySQL不同的是NewSQL将分片功能作为数据库的一部分来实现并提供了动态扩缩容的能力且对上层业务透明具备透明可扩展性。Cloud Native DB云原生数据库国内以PolarDB为代表具备池化的资源也可以实现存储资源的动态扩缩容其一般采用的主备方式来实现高可用同时其扩容和主备探活等功能需要大量依赖外部系统。(PG-XC风格) 图 2.2 数据库3种架构 (图片引自阿里云[1]) 从架构体系又分为2种流派 Shard-Nothing架构的每个节点有独立的计算和存储功能并且节点之间不共享数据 无状态SQL计算节点无限水平扩展远程存储共享存储节强SQL支持( 系统自动扩展路由 )和单机一样的事务支持跨数据中心故障自动恢复无限的弹性水平扩展Shard-Everying也叫Shard-Storage即Shared-Disk架构是在存储层做了统一和共享但计算节点是独立节点 图 2.3 数据库架构的2种流派 (图片引自论文Survey of Large-Scale Data Management Systems for Big Data Applications) 从上述图可以看出来Shard-Everying的存储是共享的前面计算节点多查询量极大的情况下就会造成共享存储压力过大导致查询性能非常低下。Shard-Nothing的则不然有独立的计算和存储节点数据不共享性能可靠市面上的NewSQL大多数都是依照Google 的Spanner/F1来进行设计的这里先简单介绍下Spanner/F1职责 F1设计的目标 无限弹性水平扩展跨数据中心故障自愈事务的ACID一致性全面的SQL支持支持索引Spanner设计的目标 管理跨数据中心复制的数据重新分片和平衡数据的能力跨数据中心迁移数据 到这里想必大家都知道什么是NewSQL了 完美的具备关系型数据库的基因且具备更加强的扩展性和性能其实NewSQL跟分布式数据库不能完全画等号的。NewSQL还是遵循事务ACIDSQL引擎那一套保证的是无缝迁移。但是分布式数据库强调的是最终一致性也是NewSQL要体现的所以NewSQL是在原生分布式数据库上构建而成的“云原生分布式数据库”有点绕嘴用简单的描述来阐述下两种事务模型大家平时用的最多的也是事务相关。 2.2 OB的技术内幕 数据库有3大特征上文介绍了OLTP 3大特征(SQL解析、事务、存储)中的2种分别为事务存储。 接下来会介绍OB的技术内幕。然后也会介绍下OB在OLAP上的表现。 先介绍OLAP 3个特性列存(解决宽表)、压缩(减少存储空间)、向量化SIMD (Single Instruction Multiple Data) 即单条指令操作多条数据——原理即在CPU寄存器层面实现数据的并行操作 2.2.1 OB存储引擎 图 2.4 OB存储引擎架构 (图片引自OceanBase) 关键设计 1基于LSM理念自研底层存储引擎未选择RocksDB 2宏块与微块存储介质微块是数据的组织单元宏块则是由微块组成。Compact操作时可以在宏和微块两个级别判断是否复用 3多Parttion多副本解耦Compact操作避免磁盘IO竞争 4控制User IO/System IO减少前台请求影响 5按行存储按列编码减少体积 6三副本Compaction的Checksum防止静默错误 7支持分布式事务 8支持BTree和Hash索引模式针对热数据做了很多优化查询效率很高本身也通过Bloom Filter Cache来加速查询 特性 低成本自研行列混存的压缩算法压缩率较传统库提高10倍。易使用支持活跃事务落盘来保证大事务的正常执行和回滚。多级转储和合并来平衡性能和空间。高性能提供多级缓存保证低延时。OLAP操作提供向量化支持。高可靠全局合并时多副本比对和主表与索引表比对校验和来保证用户数据正确性。 多类型缓存 覆盖数据访问全链路 数据缓存 Bloom Filter Cache维护缓存静态数据的Bloom Filter快速过滤无需访问的数据。当一个宏块上的空查次数超过某个阈值时就会自动构建BloomFilter Cache。 Row Cache数据行缓存在进行单行或多行访问时构建并命中。 Block Index Cache描述对每个宏块中所有的微块的范围用于快速定位微块。 Block Cache微块缓存在对数据块访问是构建和命中。 Fuse Row Cache数据在多SSTable中的融合结果。 ··· Metadata缓存 Partition Location Cache用于缓存Partition的位置信息帮助对一个查询进行路由。 Schema Cache缓存数据表的元信息用于执行计划的生成以及后续的查询。Clog Cache缓存Clog数据用于加速某些情况下Paxos日志的拉取。 总结 改进底层SSTable的存储结构通过宏和微块的模式解决写放大的问题而且可以随时调整Compact时机在挪移Parttion的时候底层数据存储单元非常适合快速移动。本身OB也会对底层存储进行监控控制Compact时机不会导致前端请求收到影响在Compcat也会针对数据进行对比防止静默导致数据错乱而且压缩比高整体体积很小。讲解存储和为什么MySQL不能Online DDL等。 主要介绍BTree和LSM的存储区别。 2.2.2 数据复制-Paxos 图 2.5 数据复制Paxos (图片引自OceanBase) 关键设计 1)Paxos与Raft最本质的区别是在于是否允许日志空洞Raft必须是连续的只能串行无法并行Multi-Paxos允许日志空洞存在应对复杂的网络环境更鲁棒。市面上有很多针对Raft的优化以Beth Index的方式去批量迭代Index等 2)一次WAL日志 示例 顺序投票策略对于主库的负面影响比较严重出于性能提升的原因数据库的MVCC使得不存在相互关联的事务以并发处理但是上述的顺序投票策略是的事务#5-#9可能呢被毫不相干的事务#4阻塞且必须Hold在内存 如果是允许日志空洞事务#5-#9就可以继续执行#4后续在落盘 2.2.3 数据复制-延展 图 2.6 数据复制延展-副本类型 (图片引自OceanBase) 关键设计 1)全能型副本拥有事务日志MemTable和SSTable等全部完整的数据和功能。可以随时快速切换为Leader对外提供服务。 2)日志型副本只包含日志没有MemTable和SSTable只参与投票和对外提供日志服务也可以参加其他副本回复但是不能对外提供服务。 3)只读型副本拥有事务日志MemTable和SSTable等全部完整的数据和功能。他的日志比较特殊它不作为Paxos承运参与投票而是作为观察者实时追赶日志然后在本地回放。对业务取数据一致性要求不高的时候提供只读服务。 2.2.4 分布式事务 图 2.7 分布式事务 (图片引自OceanBase) 关键设计 分布式事务2pc gps线性一致性事务事务流程 1)prepare生成prepare version max(gts,max_readable_ts,log_ts)。 2)pre commit推高本地Max readable timestamp。 3)commit/abort日志多数派成功之后解行锁应答客户端。 4)clear释放参与者上下文。 Percolator模型 关键设计 1事务第一个分区作为协调者其他分区作为参与者事务本地提交无需等待其他参与者返回。 2参与者粒度分区少部分分布式事务。 图 2.8 Percolator事务模型(图片引自OceanBase) 扩展 1租户级别的GPS基于Paxos保障稳定性。 2实现类似Truetime的机制在保证正确的情况下允许多个事务复用SYS减少压力。 提前解行锁 优化前一个事务持锁的时间包括了4个方方面 1)数据写入 2)日志序列化 3)同步备份机网络通信 4)日志刷盘的耗时 图 2.9 事务优化过程解析 (图片引自OceanBase) 优化后 1)日志序列化完成提交到Buffer Manager之后。 2)就开始触发解行锁操作不等日志多数派刷盘完成从而降低事务持锁时间。 3)当事务解锁之后允许后续事务进来操作同一行达到多个事务并发更新的效果提高吞吐。 2.2.5 向量化并行执行引擎 图 2.10 OB并行引擎向量化 (图片引自OceanBase) 上文提到了AP数据库3大特性向量化数据压缩列存。OB的引擎在TP和AP上都有不错的表现支持了向量化和并行执行引擎提升了规模化处理逻辑。 2.2.6 空间优化 OB的存储上是行列混存的底层SSTable由若干个宏块(Macro Block)构成, 宏块2M固定大小的长度不可更改。在宏块内部数据被组织为多个大小为 16KB 左右的变长数据块称之为微块(Micro Block)微块中包含若干数据行(Row)微块是数据文件读IO的最小单位。每个数据微块在构建时都会根据用户指定的压缩算法进行压缩因此宏块上存储的实际是压缩后的数据微块。 图 2.11 OB的存储引擎空间优化 (图片引自OceanBase) 行列混合的存储结构 SSTable由多个定长(2MB)的宏块组成而每个宏块由多个变长的微块组成。微块是读IO的最小单位。OceanBase微块有两种存储方式平铺模式(Flat)或编码模式(Encoding) 平铺模式即为通常意义上的行存形态微块内数据以行的顺序连续存储编码模式在微块里仍旧存储完整的行数据但存储组织方式则按照列的形式。OceanBase根据数据格式与语义选择多种编码手段以达到最佳的压缩效果。同时在执行过程中数据以列的组织方式载入内存提供给向量化引擎进一步提升HTAP处理性能。 图 2.12 行列混合模式图形详解 (图片引自OceanBase) OceanBase数据库提供了多种按列进行压缩的编码格式根据实际数据定义进行选择包括列存数据库中常见的字典编码游程编码 (Run-Length Encoding)整形差值编码 (Delta Encoding)常量编码字符串前缀编码、Hex编码、列间等值编码、列间子串编码等。 2.2.7 OLAP场景支撑 上文我们说了OLAP场景3大特征 向量化 列存储 数据压缩是AP场景的大杀器从上面介绍我们看到了OB是一个引擎满足TP和AP两个场景。 支持列存和行存支持向量化支持并行计算支持数据压缩根据不同的类型压缩类型也不同 美中不足的是OB在AP上支持不是特别完美还在优化中。虽然支持列存储但从原理上一个大宏块里面包含很多个小微块宏块层面数据还是按行扫描微块层面一个微块可能包含若干行这些行是按列存储的。所以OB这个架构还是行存架构只有微观层面能享受部分列存带来的好处想要彻底提升分析型性能表现需要一个彻底的列存引擎。 2.2.8 OB更多场景支持 因为高德业务比较多样化分别有结构化和非结构化的场景OB在支持高德业务的同时也衍生迭代了不同功能行产品。 OB 正常模式OB Key-Val模式OB NoSQL模式OB 纯列存模式OB Serverless模式 3. OB在高德落地过程中分应用的的融合方案、痛点和收益 OB在高德多个业务场景均有落地支撑着高德业务数据的稳定性下面将介绍三个不同架构下典型的业务落地场景 强一致金融场景的业务落地海量数据多点写入场景落地中心写单元读场景落地 3.1 强一致金融场景落地实践 业务背景及诉求 图 3.1 财务结算业务架构 高德359行财务结算服务主要服务于高德信息业务的结算和财务数据主要诉求是要求数据强一致性保障数据不丢失跨地域容灾能力。 业务痛点与技术解题 财务结算服务作为与B端商家合作的钱款计算的一环对数据一致性有极高的要求不能出现因数据不一致或最终一致而导致钱款计算错误的情况。财务结算服务业务逻辑复杂需要降低迁移改造成本最好能完整兼容原业务所使用的SQL协议平滑替换底层数据库不需要业务过多的改造。为了提升财务结算系统的数据强一致性优先选择了三机房的部署架构。 业务架构图如下图中红框内容即本次数据迁移OB时涉及到的系统改造部分使用Diamond做XDB和OB的数据源路由控制通过OMS做数据迁移并使用MAC进行迁移前后的两份数据的核验。 图 3.2 财务结算OB改造设计 为什么选择OB 1财务需要数据的强一致性和跨地域容灾而OB提供的能力完美支持该需求其提供的跨地域部署的能力可使得财务数据同时写入多地域的数据副本中即使一地域不可用后仍然能保证有完整的数据可用。并且OB的Paxos一致性协议可保证OB多副本数据写入成功后才应答成功为分布式多副本数据的强一致提供了保证。 2为了验证和解决SQL兼容问题未使用OB提供的OceanBase Client去访问OB而是使用原生的MySQL数据库的SDK驱动通过MySQL驱动访问OB在OB上回放财务全量SQL并验证通过。 3为了降低财务结算系统改造量将OB的表按不同的功能进行建设将原有分库分表的设计逻辑应用到OB分区表的分区键设计上以便上层业务可透明的切换数据源。对于数据量比较稳定的维表数据比如合同数据等将其建设为单表避免全局分布式事务提高频繁查询的性能。 解题设计核心要点 1迁移数据将数据从XDB类似MySQL到OceanBase的数据平滑迁移。 2协议兼容验证OB的SQL协议兼容能力达到业务可平滑迁移应用代码无须修改 。 迁移方案要点 数据迁移通过使用OMS进行数据迁移数据一致性的校验通过使用集团的MAC系统来核对而实时的数据写入不一致问题通过监控方式报警处理。 图 3.3 财务结算系统数据迁移设计 因财务结算非C端业务核心关注是数据的强一致型和跨地域容灾型。并在平衡成本后在OB的同城三机房、两地三中心和三地五中心的部署方案中选择使用同城三机房的部署方案既可以实现财务结算的数据一致性和跨地域容灾的目标也能一定程度上节省成本后续有需要也可以快速升级为三地五中心部署。 在完全切换OB前XDB和OB都有全量的业务数据并可通过MAC每天进行全量数据核对同时对于增量数据不一致情况及时报警处理。同时又因为XDB和OB都保有全量数据因此一旦切流遇到问题可通过开关一键回切原XDB数据库。 部署架构 采用同地三机房部署 OB原生支持能力多份数据同时写入无同步延时问题 图 3.4 财务结算部署架构 业务收益 提升存储稳定性高可用和容灾能力跨地域级别的容灾能力。强一致的存储保证对于结算财务类的数据保障较高的一致性而非用最终一致性的妥协换取其他方面的能力。提升扩展性提升数据库弹性扩缩容的能力存储横向扩展对上层系统透明极大降低数据迁移的风险。数据压缩减少数据占用的存储容量OB使用的LSM-tree结构存储最大可压缩数据至原大小的35%降低存储费用成本。平衡升级迁移OB后仍然可使用MySQL原生驱动使用MySQL5.7版本的SQL进行业务功能开发兼容原有存储(XDB)的协议极大降低业务系统改造成本。整理压测结果 目前压测数据写流量在4K左右RT稳定在1ms左右。 图 3.5 财务结算迁移OB效果收益 3.2 海量数据多点写入场景落地实践 业务背景 高德地图云同步是高德地图的基础业务服务主要负责数据的云端存储多端设备数据同步。 图 3.6 多端设备数据同步云端设计 云同步的业务系统部署架构示意图如下可以看出云同步业务用户多点就近接入一次请求系统会多次读写数据库因此可以看出系统需要支持海量数据多点写入读写性能出色的数据库。 图 3.7 云同步单元化系统架构 业务痛点与技术解题 业务上需要保证数据多端准确写入及时更新更换设备后的数据快速读取数据上随着高德业务的迅速发展云同步存储着大量数据怎么做到保证稳定性为前提追求极致性能同时极大的降低业务成本也是云同步系统需要技术解题的突破点从云同步的业务分析得出整体数据库选型要求如下 异地多活、海量数据存储、低成本 图 3.8 云同步选型详解 可行性分析 可以看出针对我们的业务场景OceanBase完全符合了业务上数据库选型要求从原理上分析原理详见上节 从成本上针对云同步的结构化的海量数据其低成本存储的高级压缩技术数据文本压缩行列存储数据特性压缩将成本压缩到极致且数据量越大优势越大。从原理上LSM-tree的底层数据结构内存处理增、删、改与批量顺序的磁盘写入极大提高了写入性能足以支持了数万级TPS的数据写入其B树的索引支撑了数十万QPS的业务读请求。从架构上其多单元同步链路OMS的秒级数据同步能力保障了多机房数据同步低延迟支撑了多机房多活的可行性。从业务上 分布式原生数据库从本质解决了业务研发需要考虑的分库分表问题。业务特性为多端数据同步可用ID作为分区键所有操作在单分区内完成极大提升读写性能。多语言SDK支撑各类业务系统极大简化对接成本同时支持SQL形式更换配置无业务入侵。 图 3.9 云同步迁移OB可行性分析 落地方案 从原理上分析了整体方案的可行性与业务收益剩下就是业务数据源切换主要分为DAO层改造、数据迁移、业务放量达到目标用户无感无损切换数据源。 DAO层业务改造使用OceanBase Client实现业务逻辑改造。 简单通用的SDKJava SDK的流式编程简单易用业务无SQL语句配置调用过程SDK封装业务无感数据迁移全量数据迁移使用集团内部工具DATAX将ID分桶并发拉取整体数千亿数据2天左右完成全量同步采用OceanBase异地备份恢复能力将数据同步到其他单元天级完成。数据比对业务自研千亿级数据对比、更新、同步框架实现千亿数据天级对比完成通用框架实现增量/全量对比/修复。灰度迁移数据双写ID维度 白名单/灰度支持比例控制核心支持按ID随时回滚。 图 3.10 云同步迁移OB落地方案 部署架构 多点写入 三地读写无网络延迟同城双主库容灾异地多活容灾 同城数据库侧容灾切流三地业务侧容灾切流三地六向数据同步 三地六向秒级同步 图 3.11 云同步迁移OB部署架构 业务收益 整体降本明显性能出色。 性能-压测数据读单单元8wqps三单元24wqps写2.8wtps读in查询写批量写入平均RT 均在23ms。 图 3.12 云同步迁移OB收益成果 3.3 中心读写单元读架构落地实践 业务背景 高德地图评价业务在辅助用户出行、交易等决策方面有着积极正向的引导且评论覆盖与POI的CTR、CVR呈正相关在本地生活大战略背景之下高德评价业务的建设帮助高德地图从平台采集数据迈入到UGC时代。 图 3.13 评价业务效果展现 从评价业务的形态来看内容生成有一定门槛写入TPS不会太高但是内容会在高德端内各个入口投放对RT响应有很高的需求作为一个读多写少的场景需要有一个支持海量数据存储可异地容灾读写性能出色的数据库。 业务痛点与技术解题 评价系统作为整体评价的入口对于性能有极致的要求整体RT必须控制在15ms以内。为了提升读性能整体采用用户就近接入三单元读数据中心写入数据对于读数据需要异地容灾能力。需要支持后续数据量的持续增长。 图 3.14 评价系统痛点分析 上述按照评价的业务场景采用OB主备集群的架构支撑着整体高德评价系统的大量读写三单的读性能得到极大提升主备延迟在秒级完全满足性能要求。 为什么选择中心写单元读 评价的业务特点决定写入TPS不会太高中心写能满足当前阶段的系统发展诉求多点写在容灾能力上更优但是会带来数据冲突等一系列问题复杂度更高。综合系统和业务的发展阶段我们选择了中心写单元读的方案。 为什么选择OceanBase 我们从成本架构特点等多个方面横向对比了多个数据库最终选择OceanBase 业务上业务不断发展数据量不断增长需要解决数据存储的瓶颈OB优异的横向扩容能力能很好的解决这个问题。成本上OceanBase自研的基于行列混存结构/高效数字编码的存储压缩技术将成本压缩到极致能有效的降低评价数据的存储成本。原理上基于LSM-Tree的底层数据结构极大提高了写入性能足以满足评价场景的写入诉求。基于B树的索引能满足评价场景大量读的查询诉求。架构上基于OceanBase主备库的架构利用集群原生的复制能力实现秒级同步可靠性高。 部署架构图 中心写入 中心写单元读架构更加简单不用担心数据覆盖的问题 同城双主容灾异地多活容灾 同城多机房容灾切流三地读容灾切流 三地主备数据同步 利用集群间原生同步能力秒级同步 图 3.15 评价系统部署架构 核心要点 张北中心主集群可读可写实现强一致读。上海和深圳为备集群通过OB原生的集群复制能力同步秒级延迟实现非强一致异构存储的高流量低耗时读业务。 数据一致性保障 实时OB主备之间通过集群原生的同步能力可靠性非常高基本不需要担心。离线提供离线分析的兜底手段通过MAC平台T1分析监控数据一致性。延迟监控OB主备之间通过集群原生的主备同步延迟监控能力进行监控集群级别的复制能力性能很高正常的延迟都在秒级。 上述采用OB主备集群的架构支撑着整体高德评价系统的大量读写三单的读性能得到极大提升主备延迟在秒级完全满足性能要求。 索引设计实践 面对大数据量的C端场景基本都需要建立分区表对数据分片实现存储的横向扩容下面我们就讨论分区场景下的索引设计。评价场景下最核心的模型就是评价基础信息其他如评价标签、评价元素、评价评分等都可以通过评价ID关联出来因此我们主要讨论如何设计索引实现评价主表appraise_base高效查询。 1分区键设计 最开始我们使用评价appraise_id作为分区键 partition by key(appraise_id) partitions 512 这么设计的考虑是通过评价ID进行分区数据分散比较均匀同时通过评价ID也是高频查询这种方案是个比较常规且通用的设计表面上看起来并没有什么问题。但是按照线上流量实际压测时发现一直达不到预期效果。我们开始静下心来和OB同学一起分析原因 分析业务流量发现大多数查询都是评价者appraiser_id维度进行查询业务场景是查询用户在POI下是否首评、POI详情页展示用户最新一条评价这部分查询都是都是走了全局索引而全局索引场景下索引和数据不一定在同一个节点上大多数请求都需要经过一次跨机分布式事务消耗了较多数据库资源。 对线上查询流量分析 用户维度单个、批量查询占比75%通过评价ID查询占比15%评价对象维度查询/按时间分页查询占比10% 到这里问题原因就比较清晰了因为分区设计的缺陷导致大量的查询走到一个低效的索引上整体性能上不去这里引出了分区设计一个很重要的原则——在main SQL 维度建立分区键分区索引的性能是最好的。 因此改为评价者appraiser_id维度建立分区键 partition by key(appraiser_id) partitions 512 2索引设计 分区键确定后其他维度的查询一般都设置为全局索引分区键维度的多条件查询设置为本地索引具体为 PRIMARY KEY (appraise_id, appraiser_id),
KEY idx_appraiser_id_gmt_create (appraiser_id, gmt_create) BLOCK_SIZE 16384 GLOBAL,
KEY idx_targetid_gmt_create (appraise_target_id, gmt_create) BLOCK_SIZE 16384 GLOBAL,
KEY idex_modified_status (gmt_modified, status) BLOCK_SIZE 16384 GLOBAL
partition by key(appraiser_id) 评价者ID维度appraiser_id设置分区键评价IDappraise_id设置为主键查询评价对象维度appraise_target_id设置全局索引查询 这里有没有发现idx_appraiser_id_gmt_create的索引设置有点不太合理索引被设置为全局索引了这里可以设置为性能更好的本地索引原因为appraiser_id已经是分区键通过appraiser_id路由到的分片上有全量的的数据通过本地索引完全能定位到数据不需要走全局索引查询这个索引最终改为本地索引 KEY idx_appraiser_id_gmt_create (appraiser_id, gmt_create) BLOCK_SIZE 16384 LOCAL, 3分区表下的数据更新 业务上评价数据都是通过评价IDappraise_id进行更新在实际压测中发现CPU 会飙升到70%左右排查发现通过appraise_id更新时不带分区键定位分区有额外的成本因此在更新条件中加入了分区键这样在相同的压力下CPU 降至20%以下。 评价系统-索引设计总结如下图在分区表场景下有一个好的索引设计非常重要。 图 3.16 评价系统索引设计实践总结 业务收益 新的数据库架构完全支撑整体评论体系的读写性能分布式数据库不用担心后续的海量数据增长导致重新分库分表整体压测结果如下读/写2w平均响应稳定在12ms 图 3.17 评价系统迁移OB收益成果 4.OB在高德落地的最佳实践总结 4.1 关于为什么选择OB 在第二节第三节分别讲述了OB的技术内幕和高德OB的落地场景但是详细考虑为什么选择OB就是关于数据库的选型是怎么思考的我想说“一切基于业务场景不同业务适合考虑不同数据库”如果业务只有一个很小的场景几十万条数据几百QPS的查询且数据基本不增长那单实例的MySQL就足够满足要求以云同步业务3.2节看云同步业务特性单元化、海量数据存储、海量请求而云同步经历Mongo-Lindorm-OceanBase为什么进行迁移同时为什么不使用MySQL我们对比如下 PS关于为什么我们业务上既考虑关系型数据库又考虑NoSQL数据库我们业务上本质是结构化数据适合关系型数据库但是整体业务查询简单对于NoSQL或者KV同样可以支撑我们的业务。 表 4.1 数据库选型属性信息 我们最关注的三点稳定性、业务支撑、成本三个角度综合考量OceanBase是我们看到的最优解确定了数据库我们就要选择OceanBase的部署架构。 4.2 OceanBase部署架构选择 从上面的项目实践可以看出我们对于异地多活的部署使用了两种架构多点写入和中心写入多单元读针对OceanBase也同样的是两种不同的架构 4.2.1 架构选择-多点写入 对于多点写入的部署架构三个单元的数据库相互独立通过OceanBase提供的数据同步工具OMS进行三地六向的相互同步此种部署架构优势如下 用户就近接入读写对应单元无数据延迟实现完美的异地多活各单元异地容灾机房故障随时切流用户无损 图 4.1 OB单元化部署架构 4.2.2 架构选择-中心写单元读 对于中心写单元读系统架构主要采用OceanBase的主从架构整体优势如下 整体对于读支撑能力提供三倍同时节省了网络耗时主从架构为集群内部机制自动同步运维更简单 图 4.2 OB的中心写单元读架构 4.2.3 架构选择-同城多机房读写 用户请求到业务系统无法避免的物理延迟3050ms同城多机房灾备无法媲美异地灾备能力架构简单运维方便 4.2.4 关于多单元数据同步 其实中心写单元读也可以采用OMS但是没必要 表 4.2 多单元数据同步对比 4.2.5 架构选择结论 结论不用结构有不同的优劣具体采用哪种架构要看业务需求如果业务对读延迟没有强要求可采用主备模式否则选择多单元OMS同步模式而针对本身就是单元化的云同步业务多点写入是我们最好的选择。 4.2.6 多点写入系统的问题与解决方案 关于多点写入的系统3.2节云同步系统举例整体会有很多疑问点例如 云同步系统是否业务一定要单元化不单元化会有什么问题从成本考虑已经单元化三个单元是否可以不存全量数据单元化系统容灾切流是否会有问题 4.2.6.1 云同步系统为什么要实现单元化 业务背景分析 1从业务要求上一次请求云同步系统需要与数据库多次交互数据库必须是张北、上海、深圳三中心来降低网络延迟。 2从用户访问上通过APP访问目前的方式是就近接入但是用户的连续两次请求很可能跨中心。 3三单元数据库同步是一定存在延迟的只能缩小延迟但是不可避免例如网络物理延迟。 异常情况举例出现数据缺失与覆盖详见4.2.7.2 用户连续两次请求更改同一条数据但是请求跨中心第一次张北中心第二次上海中心会产生什么情况 1用户第一次请求张北更新成功。 2用户第二次请求上海更新成功。 3如果两次的请求的间隔小于同步延迟那么数据同步过来后上海中心的数据最新数据会被张北中心的数据覆盖张北中心的数据最新数据会被上海中心的数据覆盖会产生数据的不一致性。 单元化解决的问题 1 将用户请求封闭在同一中心单元解决可能产生的数据不一致性问题。 2用户最多产生一次网络延迟入口层识别用户单元分发时可能产生转发到其他单元业务与数据库多次交互均无额外网络延迟。 4.2.6.2 单元化系统每个单元是否要存全量数据 1从成本角度看单元化系统只存储对应单元数据不需要数据同步同时存储成本很低优点。 2但是三个单元存储非全量数据业务将无法进行容灾切流只能依靠数据库同城容灾做不到异地多活容灾缺点。 结论要看系统对于容灾的稳定性要求如果要做到异地多活随时切流容灾则需要每个单元存储全量数据。 4.2.6.3 单元化系统容灾切流是否会有问题 单元化系统解决了日常情况的数据一致性问题但是如果系统发生容灾切流依然会产生数据一致性问题需要进一步解决。 图 4.3 单元化部署同步延时 4.2.7 切流态的数据缺失和覆盖解决方案 4.2.7.1 什么情况下会有数据缺失 对于数据缺失很好理解用户从一个单元切换到另外一个单元如果用户前一个单元的数据刚写入但是由于同步链路延迟用户已经切换到其他单元但是之前写入的数据还没同步过来这样就产生了数据缺失。 4.2.7.2 什么情况下会有数据覆盖 这是个极端情况不过也有可能发生如下图如果用户先执行1后执行2在执行1和2之间发生了用户单元切换如果数据延迟大于用户操作会发生什么会造成数据永久性差异同时张北OB存在数据错误。 对于张北OB如果数据延迟则2先进行1通过同步链路进行最终数据id 1 name a。对于深圳OB则1先进行2后进行最终数据id 1 name b。 图 4.4 数据覆盖问题详解 4.2.7.3 解决方案是什么 业务侧保证禁写时间同时要求OMS不能有长延迟。OMS数据同步时保证数据不被覆盖目前OMS支持启停后重新追数据会比较时间戳所以我们在切流预案中集成了OMS的启停。OMS延迟越低风险越小。 图 4.5 避免数据覆盖设计 4.2.7.4 OMS同步怎么降低延迟 OMS同步链路的拆分与相互独立。 同步链路可以从数据库维度拆分到表维度相互链路独立无影响同时提升同步性能。 图 4.6 OMS如何降低延时 4.2.7.5 OMS降低延迟效果 在我们降所有表独立成三条链路后测试数据结果峰值写入百兆/秒同步延迟在10s20s之间。 图 4.7 OMS 降低延时效果 (注因数据敏感部分数据脱敏) 4.3 针对于OceanBase我们要选择分区表还是单表 4.3.1 业务设计选择-分区表OR单表 业务增长迅猛一定选择分区表。注意目前OceanBase的分区数量最大8192且分区数在创建时即固定不可自动分列。 图 4.8 OB表设计选型详解 4.3.2 业务设计选择-全局索引OR局部索引 局部索引索引和数据相同的分区规则在同一机器上可避免部分分布式事务。全局索引不管是全局分区索引还是全局不分区索引其都可能导致索引和数据不在同一机器上每次写入都是跨机分布式事务。换句话说全局索引会影响表数据写入性能。 4.3.2.1 使用全局索引的场景 有除主键外的全局唯一性的强需求需要全局性的唯一索引。查询条件没有分区谓词无高并发写入。避免全局扫描可构建全局索引但一般限制在4条全局索引内。 4.3.2.2 全局索引、局部索引性能对比 图 4.9 OB索引间性能对比[2] 引用自https://www.zhihu.com/question/400141995/answer/2652474150 4.3.2.3 局部索引读写注意事项 针对局部索引的读写一定要在请求时指定分区键这样在OceanBase实际处理时才会直接确定对应分区整体性能会有明显差距以高德评价系统为例Update场景下命中分区键CPU使用率从75%降低到20%以下。 4.3.2.4 全局索引使用的注意事项 1)使用全局索引需要避免扫描行数过大扫描行数过大会带来大量RPC调用导致RT过高建议对大查询做分批查询。 2)不建议使用全局索引做更新操作基于全局索引更新性能比较查QPS高时系统负载比较高。 4.3.3 业务设计选择-OBKV OR OB普通版本 一句话解释OBKV版本和OB普通版本OBKV版本没有SQL解析优化器很多SQL需要业务手动优化SQL指定索引等但KV版本比普通版本要便宜。 表 4.3 OB版本之间的成本对比 PS目前OBKV版提供了SDK支持Java/Go/Rust语言。 4.3.4 业务设计选择-什么时候使用复制表 复制表概念OceanBase有一种表类型叫做复制表这种表数据不像分区表一样做分片存储也不像单表一样只存储于单个Observer上而是会将全部数据完整的存储在所有Observer上。 主要优势复制表数据存在于所有Observer, 数据库在制定查询计划时会做针对性优化尽量保证从本地机器获取数据避免远程调用。 使用场景如果某张表数据很少且业务上这张表需要与其它分区表做大量JOIN查询可以将这张表设置复制表提升JOIN性能。有个常见的例子我们系统中通用会有一些基础数据表比如城市表、类目表等这类表如果需要与其他表做JOIN查询可以考虑设置成复制表这样可以避免跨分区JOIN。 4.3.5 业务设计选择-Leader副本是否要分散到各个Observer上 OceanBase一个Zone通常有3个Observer节点默认情况下系统中所有分区表Lead副本只分布在一台。Observer上这台Observer抗住这个Zone所有读写请求。我们可以考虑将Leader副本分布到所有Observer上这样可以提升整个系统的资源使用率。但是这样也会带来其他问题如果我们系统中存在大量跨分区的读写操作会增加很多远程调用导致读写RT升高。 大多数情况下我们使用系统默认配置就行只有当遇到数据库性能问题时才考虑打散Leader副本并进行压力测试验证效果。使用场景总结如下 分散Leader副本系统中大部分查询都可以使用局部索引完成只有少量查询使用全局索引且系统中写操作使用分布式事务场景也不多。 不分散Leader副本系统中有一定比例的全局索引或写分布式事务这种情况下打散后会导致这部分读写操作RT升高。 4.3.6 业务设计选择-主键和分区键设置 主键Oceanbase作为传统关系型数据库替代品经常使用在OLTP场景作为业务系统主数据库使用这种场景下推荐使用自增主键便于后期维护、数据异构等。Oceanbase虽然自带自增主键但是只能保证在一个分区内具有单调性不推荐使用。建议使用外置分布式ID方案比如“数据库号段模式” 或者 “雪花算法”等。 分区键 1Oceanbase分区方式设置很灵活支持多级分区、Hash和Range函数分区通常情况下我们使用最多是基于某一个字段Hash分区。 2分区键选择上需要综合考虑查询方式和数据热点问题通常情况下我们可以使用查询最多的一个维度作为分区键保证大部分查询可以有最佳的性能。 3如果系统中有一组表彼此关系比较密切经常一起JOIN使用这组表可以使用相同的分区方式且设置相同的分区数量数据库可以保证这组表同一个分片下的数据分布在同一个Obsever上。比如订单表和订单明细表可以都使用用户ID为分区键。 4分片数量要适宜分片太大对查询性能有影响这个要注意按自己场景设定并测试验证。 4.4 业务落地的瓶颈 针对云同步这样海量的读写同时针对节假日出行高峰我们的流量即可能翻倍经过压测我们发现了部分瓶颈。 4.4.1 瓶颈-流量稍高Client明显报错超时 Java Client代码问题在发起请求处理链接不合理使用Synchronized。升级最新包即可解决。 图 4.10 瓶颈Client延时问题 4.4.2 瓶颈-读写流量增加业务超时明显 随着压测的增加平均RT明显上涨且失败超时明显增加。原因Proxy侧性能瓶颈。 图 4.11 读写流量增加业务超时明显注因数据敏感部分数据脱敏 4.4.3 瓶颈-业务机器扩容失败无法链接数据库 扩容失败提示无法连接数据库。业务系统不断重试依然无法连接。 原因是单Proxy链接数有上限。 4.4.4 瓶颈解决-海量数据云上部署架构优化 OceanBase公有云正常部署架构为Client - SLB - Proxy - OBServer如下图 4.4.3 左图但是针对海量数据请求可能存在瓶颈单Proxy的链接数读写性能不足以支撑业务请求时可以进行架构优化进行水平拆分多单元OBServer之间可以采用OMS进行数据同步针对高TPS的写入同时写入数据量很大的情况下OMS同样可以进行拆分正常情况下一条同步链路支撑两点数据库之间的全量同步优化架构可以拆分成表维度互相同步详见4.2.7.4节。 图 4.12 针对海量请求的OceanBase水平拆分 4.4.5 业务落地-优化效果 在刚刚过去的出行高峰云同步业务峰值OceanBase整体RT平稳在23ms 图 4.13 海量数据延时优化效果 注因数据敏感部分数据脱敏 4.5 当然我们也趟过一些坑 4.5.1 OB KV版不支持SQL优化器使用索引需要程序指定 OBKV版本为了达到最大的性能优化针对我们没有复杂查询的业务我们采用OB KV版本此版本不支持SQL优化索引自动选择的能力需要程序指定示例如下 我们创建了item_uid, item_id的联合索引在OB KV如果业务需要走索引要制定indexName如代码行6。 TableQuery query obTableClient.query(table).setScanRangeColumns(item_uid, item_id);for (String itemId : itemIdSet) {query.addScanRange(new Object[]{uidStr, itemId}, new Object[]{uidStr, itemId});}QueryRESultSet rESults query.indexName(INDEX_UID_ITEM_ID).execute(); 同时正如上面提到请求需要指定分区键我们在使用时一定注意指定分区键我们这里分区键是uid。 public TableQuery queryWithFilter(int uid, String table, ObTableFilterList filterList) {return obTableClient.query(table).setScanRangeColumns(uid).addScanRange(uid, uid).setFilter(filterList);} 4.5.2 OMS clog丢失、OMS同步明显延迟触发报警 在第四节开头的多点写入部分介绍了三地六向数据同步的架构OMS会有Store节点而Store节点的数据是在内存存储的在我们压测时发现当写入数据量过大时会导致内存覆盖导致同步日志Clog丢失针对此种解决方案为内存日志落盘保证日志持久化那如果磁盘满了怎么办目前磁盘余量会比较大同时加设磁盘的相关报警值班人员随时关注。 图 4.14 OMS 数据链路 4.5.3 主从架构高德评论库上海备集群缩容后无法提供服务 业务解决在发现问题时第一时间做了业务切流整体业务无影响这也同样体现出异地多活的重要性可以迅速容灾。 直接原因集群缩容把SLB切换到了不支持备集群的OBProxy版本上导致服务不可用。根本原因公有云上OB集群的OBProxy默认是和observer同机部署3月初为了配合支持主备库和POC测试将OBProxy部署模式切到了独立支持主备库的实例和版本部署但是元信息记录没有修改仍然为混部模式。导致本次缩容过程中识别到混部模式后认为需要修改SLB挂载的OBProxy信息从而挂载到了现在的不支持主备库的版本业务访问异常。 问题解决方案 OBProxy运维操作自动化优化避免操作疏漏引入的后续问题支持创建各版本OBProxy集群、SLB绑定OBProxy等。释放节点操作新增静默期有问题可以马上回滚。 4.5.4 OceanBaseServer 部分节点CPU被打满 问题现象某一天中午突然收到告警CPU被打满整体现象如下图4.5.2 和4.5.3 图 4.15 OB 异常节点CPU 注因数据敏感部分数据脱敏 图 4.16 OB 正常节点CPU注因数据敏感部分数据脱敏 问题分析通过阿里云SQL分析发现数据库存在部分慢查询以及大量KILL QUERY请求记录 图 4.17 云SQL分析CPU问题效果注因数据敏感部分数据脱敏 问题原因 出问题SQL的业务场景通过工单ID查询工单的回调记录倒序取100条 select gmt_create,id from table a where a.feedback_idxxxx order by gmt_create asc,id DESC limit 100; PRIMARY KEY (feedback_id, id),
KEY idx_gmt_create_id (gmt_create, id) BLOCK_SIZE 16384 LOCAL
partition by hash(feedback_id) 这个SQL存在两种执行计划 计划A使用主键索引走feedback_id维度的主键索引查询feedback_id为分区键。 计划B使用本地索引idx_gmt_create_id走feedback_id 维度的本地索引查询。 正常情况下工单的回调记录就几十条小ID执行计划选择的是A但是那天刚好有个工单有某种异常导致下游一直发送回调消息回调记录达到5w条大ID这时候OB引擎认为计划B性能更佳根据OB执行计划的淘汰机制一段时间的执行计划切换为计划B。这时候小ID的查询也切换到计划B上小ID SQL走了idx_gmt_create_id local索引导致性变差超时引起应用大量发起KILL QUERY最终导致CPU打满。 小ID走本地索引性能变差的原因 与OB确认是排序引起的性能问题具体为正向排序当前3.2.3.3版本做了性能优化目前版本逆序排序还未做优化从而出现Desc排序耗时超5秒的情况。大ID执行时扫描的记录数达到Limit时会提前结束扫描全部子分区而小ID查询时总记录数不足Limit在未做优化的时候需要扫描全分区导致性能问题出现。 解决方案 为解决大小ID查询性能不一致的问题需要重构idx_gmt_create_id索引增加feedback_id筛选列避免全分区扫描。具体索引为KEY idx_feedback_id_gmt_create_id (feedback_id, gmt_create, id) BLOCK_SIZE 16384 LOCAL。OB侧做逆序排序优化新版本已修复。 5. 高德云原生生态未来规划 高德本着“促科技创新与生态共进”初心通过技术创新的手段连接真实世界做好一张活地图让出行变得更加美好。在过程中我们会通过技术的手段去高效的迭代产品提升用户体验也会通过技术的手段去降低成本涵盖人力成本和资源成本。 其实互联网发展到现在这个阶段2个关键词“降本”和“提效”也非常重要。我们已经从“单体架构”过度到“分布式架构”到现在的“微服务架构”进入到未来的“云原生架构”数据也从当初xG衍生到现在的xPB级别。伴随着ChatGPT出现算法也达到了一个高光的时代“算法大数据”的方式可以让模拟人类大脑的方式去思考去帮助人类提效这类新的技术也让机器完成了涅槃拥有了生命我们称之为“硅基生命”。 这么一看科技是可以促进创新、促进社会进步的拥抱新的技术对我们来说显得尤为重要。因为要在这个生态环境下提供更好的服务是我们的初心我们不但要拥抱新技术还要反馈社会促进科技创新促进生态发展。那么回过头说说我们在云原生上是如何做“降本”和“提效”的。 因OB也是云原生数据库我们在云原生后续的规划里会继续跟OB合作在降本和性能涵盖AP场景做更大的突破。高德在Serverless上已经取得了100w/QPS成绩我们也会继续发挥这个优势利用云原生行业无关化架构提升开发效率比如利用Serverless能大幅降低研发成本、提升人效并加快迭代速度让业务更快一起做好极致的用户体验。 [这里做一个云原生的概念回顾因为可能读者会产生一个疑问OceanBase不是分布式数据库吗什么时候变成云原生数据库了。] 云原生(Cloud Native)其实是一套架构体系说到体系其实就会衍生出方法论。Cloud的含义是应用和数据都不在机房或者IDC中而在N多机器组合的云中.Native设计之初就是以云架构为基础提供资源池化、弹性和分布式服务等核心能力。 非原生到云原生的转化路径为 1、DevOps迭代与运维自动化弹性伸缩、动态调度 2、微服务Service Mesh、声明式API 3、容器化 4、持续交付 OB提供了租户的概念资源池弹性调度都是相互隔离的数据非常安全。本身OB的组件也都是服务化的基础服务也可以跑到容器里。做到Native架构所要求的特性而且OB的资源都在云上。从这些来看OB就是一个云原生数据库了。 5.1 高德与OceanBase合作后续展望 上文也简单的介绍了OB的技术内幕我们直接说结论。DevOps和持续交付这里不提因为现在每款数据存储工具都会做而且都会提供极致的用户体验让运维变得更加简单。这里我们想说的是OB的数据压缩技术OB对数据压缩和路由上做了很多优化与创新单说数据压缩针对不同的列类型提供不同的压缩技术尽量使得存储量变得小而不失查询效率。 这里是否会产生一个疑问高德为什么这么在乎数据压缩和存储空间大小。其实可以先思考下这个问题大家在使用高德地图的时候体感只是当前使用的功能。为了更好的用户体验我们做了很多数据和算法上的事来提升用户体验这也导致高德数据体量非常大所需要的成本会很高可能都是指数的级别从公司的角度来看优化这块对我们来说收益很大不但可以节省成本还可以降低耗电量保护环境。从另外一个角度来说做极致的优化也是我们的追求。 总结下未来跟OB合作的事项以及详细规划。事项如下 因高德数据体量很大后续会持续落地OB( 常规结构化和非结构化版本)探索OB的AP能力替换ADB方案探索Serverless版本 图 5.1 高德与OB后续合作展望 5.1.1 海量数据项目 - 结构化数据 高德有许多结构化的数据存储在Lindorm中Lindorm本质是列存多副本冗余架构本质上跟OB一样高可用架构。列存的数据库对于大数据计算其实是很友好的如果一个Sum的计算其实只要读一次列值然后计算就可以(这里是一个列不涉及IO的计算) 。虽然结构化数据也支持但是毕竟场景不是很合适因为我们有复杂的查询在里面这里就比较适合迁移到OB上从另外一个角度来说OB的多列类型压缩在成本上也有很大优势。 后续我们会持续把结构化数据场景的业务迁移到OB上比如存储高德足迹结构化存储目标降本50%以上。 当然迁移后我们也可以享受OB线性优化的收益可以压缩数据的节点数量达到最小当大促或者量大的时候自动进行弹性扩容而且因OB具备分布式的能力我们也无需关注负载均衡的问题完全实现了自动化透明扩容。 图 5.2 OB弹性扩容设计 5.1.2 海量数据项目 - 非结构化数据 在高德的复杂场景里我们处理结构化数据还有许多非结构化存储场景这里这的不是简单的KV模式一个Key对应一个Val。我们其实用的更加复杂因为我们的非结构化的场景需要动态列-Schemaless能力也会和固定表结构混用这样就显得十分复杂。如果再加上一个多版本的数据保留那么在查询上就会更加复杂。你们以为这就完了吗我们还会加上一个列级的TTL。这种复杂的组合真的很考验数据库的能力和性能。OB在收到我们的需求后响应也是非常的及时快速的开发出NoSQL多版数据版本来支持我们目前已经满足了我们大部分场景。列级的TTL也已经开发的差不多了近月就会提供出一个稳定版本让我们使用。 目前在非结构化数据场景也一直和OB在一起探索目标把打车的特征平台典型的KV场景迁移到OB上预计降本目标50%以上。 如果只是单独提出“多版本、动态列、列级TTL”组合能力看着只是稍微复杂点其实还好。 如果说我们每个应用的数据量级都是过百T的存储量几百张表读峰值在百万级/S写峰值在十万级/S。 这么看是不是会体感更好点。所以针对这块降本还是很可观的具体降本在30%-40%。 5.1.3 探索OB的AP能力替换ADB方案 OB目前的引擎能力已经支持了AP场景但是因为OB的目前的表现还是行极少能吃到列存在AP上的表现。下半年OB推出纯列存储引擎在路由和数据模式上(冷热数据)也做了很多优化性能会提升至少3倍数。我们也会在下半年把现有AP场景切一个试点到OB上目前预计降本20%。 这里不是对OB的OLAP场景的性能要求苛刻我们还是本着降本提效的思路要压榨出OB极致的性能因为我们在大数据分析场景对数据分析的实时性要求很高只要在快速的效果下才能提供极致的用户体验。而且同一个租户集群里我们可以同时享受到OLTPOLAP双引擎的优势和收益降本收益还是很客观的。 图 5.3 OB的OLAP方案 当然我们也会把OB引入到交易的场景里在交易的复杂场景里OB也会表现的非常好。 图 5.4 OB交易场景探索 5.1.4 Serverless版本的探索 高德本身已经在Serverless上取得了很多成绩百万级QPS。我们有很多Serverless落地经验也会跟OB一起尝试落地Serverless版本的OB再次降本。 资源按需使用规格动态升级资源按需使用底层存储空间扩容 因OB是多副本模式转存模式多数派模式扩容时可用。 图 5.5 OB在Serverless上的探索 5.2 极简架构建构云原生Serverless和组装式研发生态 说到组装式研发这并不是一个新词这种架构模式其实很早就存在了只是每个公司实现的方式不同。高德针对组装式研发进行了调整因为对我们来说数据流转就是2大属性“Request和Response”。但是从业务组合的视角我们其实只有“Input和Output”。从架构的视角就更加简单明了也更加灵活了。 我们其实只要针对输入和输出进行加工然后通过流水线的方式把流程编排起来整个业务流程和数据流转就会非常清晰我们也会根据公共特性进行封装变成通用组件进行复用大大提供人效成本和降低后续维护成本。不再担心面对业务孵化和不敢改的局面真正做到从人到机器再加上业务迭代上的一石三鸟的收益。(因辅助的工具比较多这里不深入叙述后续可以单独写一个专题) 组装式不单单可以用到应用上还可以用到Serverless的FaaS里其实我们现在好多服务已经进化成Serverless的BaaS模式。整个组装式已经深入到Serverless生态里面。我们也会继续建设Serverless生态应对初心促进科技发展开源高德Serverless FaaS的Runtime脚手架到社区让大家可以快速复刻高德的Serverless落地方案。我们已经在“交易、出行、广告、车生态”等多个场景里落地了感兴趣的同学可以去搜索“高德云原生之Serverless体系建设实践”。 整体抽象如下3点 组装式研发乐高组件动态编排快速迭代提升人效降低维护成本快速迭代业务。Serverless生态建设更加丰富的脚手架和工具落地快速降本。存储层面支持Serverless一个函数通杀所有端云一体语言无关降低研发门槛。 图 5.6 Serverless 端云引擎一体化探索设计 6. 参考 [1] 阿里云. PolarDB-X技术架构[EB/OL]. 2023-07-18[2023-07]. https://help.aliyun.com/document_detail/316639.html [2] PolarDB-X. PolarDB-X、OceanBase、CockroachDB、TiDB二级索引写入性能测评[EB/OL]. 2022[2023-07]. https://www.zhihu.com/org/polardb-x. [3] Wu L, Yuan L, You J. Survey of large-scale data management systems for big data applications[J]. Journal of computer science and technology, 2015, 30(1): 163-183. [4] https://glossary.cncf.io/serverless/ [5] https://developer.salesforce.com/docs 推荐阅读 如何在高德地图实现自动巡航效果走近高德驾车ETA预估到达时间ARHUD驾车导航技术概览高德正式发布HQ Live MAP 关注「高德技术」了解更多