贝壳找房:基于OceanBase构建实时字典服务的实践 | OceanBase案例

news2024/9/22 11:23:03

贝壳找房作为领先的居住服务综合平台,一直在推进居住产业的数字化与智能化升级。该平台通过汇聚并赋能优质的服务者,旨在为中国广大家庭带来涵盖二手房买卖、新房交易、房屋租赁、家装、家居以及家庭服务等全方位、高质量且高效的居住服务体验。

在贝壳找房的指标体系中,由于大量指标需要在实施场景精确去重,因此,需要构建实时字典服务,而实时字典服务对存储要求极高,需要存储服务能支持每秒十万级以上数据量的读写、支持数据持久化和保障数据的唯一性。结合现有存储系统及需求的场景特点,贝壳在2个测试对象即HBase 和 OceanBase中选择了后者,在上线OceanBase后,贝壳获得了更高的查询性能和稳定性,更低的硬件成本和运维成本。

解决精确去重计数痛点,贝壳构建实时字典服务

在数据分析领域,精确去重计数(Count Distinct)是一种常见的需求。在贝壳找房的指标体系中,大量指标的计算都需要精确去重计数的支撑,比如带看量、委托量、DAU、MAU等等。对OLAP引擎来说,精确去重计数支持是一项基础的能力。

传统精确去重计数实现方式是基于原始数据进行计算,保留了明细,使用灵活,适用于支持明细需求,但是其在查询过程中需要多次进行数据Shuffle,在数据量大(高基数)时资源消耗大,性能难以保障。为了解决这个问题,在大数据领域普遍都会采用近似计算方法(如 HyperLogLog、Count-Min Sketch 等),这些技术可以较大程度上减少计算开销,但同时也会对计数结果引入一定的近似误差,无法支持精确去重计算。另外一种常用的方法是基于位图(Bitmap)实现精确去重计数,其思路是将明细数据的值对应到一个bit位上,元素存在则该bit值为1,不存在则为0,在精确去重计数时,只需统计Bitmap中1的个数即可。但是,基于 Bitmap 精确去重计数方法也有一定限制,即要求去重字段类型为整数型类型。如果需要支持对其他数据类型的字段采用Bitmap进行精确去重计数,就需要构建全局字典,将其他类型数据(如字符串类型)通过全局字典映射成为整数类型,即字典编码+Bitmap。

为了支持实时场景下,对非整型数据的快速精确去重计数,需要构建实时字典服务,支持在Flink任务中利用实时字典服务,将非整型数据转换为唯一整型编码,存储到下游OLAP引擎(例如StarRocks等),然后利用OLAP引擎本身支持对整型数据进行Bitmap精确去重计数特性来实现快速的精确去重计数。

简言之,实时字典服务的目的是将实时数据流中的非整型数据映射为整型数据,主要功能如下:

  • 通过接收调用方传递的非整型数据(key),返回对应的整型数据(key:value)。
  • 相同的key永远返回相同的value,不同的key永远返回不同的value,即要保证数据的持久化和唯一性。

因为是在实时数据流中使用,所以实时字典服务必须做到低延迟,能快速响应调用请求。

实时字典服务在整个数据处理流程中的角色如下图所示,在实时ETL过程中,调用字典服务,传入原始数据,返回原始数据对应的字典值,完成替换后写入OLAP引擎。

1686713915

字典服务包括两层:计算层和存储层。计算层负责字典注册、数据查询和处理,与调用方和存储层进行交互。存储层提供字典数据的存储和查询服务。

   1.  计算层

计算层包括字典注册和字典生成两部分。

注册字典:对于需要将字符串转换为整型数值的字段,需要进行字典注册,一个字段对应存储服务中的一个字典表。字典数据的存储和查询将以此表为基础。

字典生成:调用方通过字典id和原始值列表获取原始值列表的字典值。查询流程如下图,包括三个步骤:1)根据原始值列表查询字典表,拿到结果数据;2)对结果中不存在的原始值,生成新的字典值;3)返回1和2的结果。

1686713929

   2.  存储层

存储层负责字典数据的存储和查询,是字典服务实现的基础。必须有足够高的可靠性来保证数据的不丢失、不重复,每秒处理十万级数据量以上的读写性能来保证服务调用的低延迟,所以选择合适的存储服务十分重要。

实时字典存储服务选型:保证数据不丢不重

要满足实时字典服务的存储需求,存储服务需要能支持每秒十万级以上数据量的读写、支持数据持久化和保障数据的唯一性。最重要的是数据持久化和数据唯一性,既不能丢数据,也不允许数据重复(同一个key对应多个value,多个key对应同一个value)。根据公司现有存储系统及需求的场景特点,本次选型选择了2个测试对象:HBase和OceanBase。

1.环境准备

OceanBase和HBase测试集群均采用3台Dell EMC PowerEdge R640服务器节点组成,节点配置规格为:48C/128G/1.5T Nvme SSD,所有的测试任务均运行在同一个Hadoop 实时集群。HBase版本为1.4.9,HBase集群由HBase DBA协助部署和配置,OceanBase版本为3.1.2,使用默认配置。

2.测试数据

测试过程是通过spark streaming实时任务消费topic(starrocks-prometheus-metrics),借助该topic的数据量(每秒4万~8万之间),对每条数据生成uuid,最后批量调用字典服务生成字典,batchDuration设置为1秒。通过增加实时任务的个数提高数据量来加大底层存储的压力,通过观察实时任务的延迟指标来判断存储服务的吞吐能力。

压力测试分为如下三个等级,不同等级测试时间持续10分钟。

1686713967

3、测试过程与结果分析

1)HBase测试

   HBase本身是持久化的,可以保证数据不丢失;支持批量查询(get(List<Get>));通过唯一自增(incrementColumnValue)可以保证value不重复;通过事务写(checkAndPut)可以保证key不重复。

   HBase可以独立满足字典服务的数据处理流程:

    • 首先通过调用get(List<Get>)接口批量查询字典表。
    • 对于字典表中不存在的数据,调用incrementColumnValue接口,批量生成唯一自增id,保证字典值不重复。
    • 通过事务写checkAndPut将key:value数据写入字典表,写入成功表示字典值生成成功,写入失败表示原始值已存在字典值,保证相同的key不会写入两次。
    • 使用上一步写入失败的数据,再一次调用get(List<Get>)接口查询字典值。

1686714090

   为了提高数据的读写性能,对字典表进行region预分区,将数据分散到不同的region server,本次测试使用了HBase DBA推荐的HexStringSplit分区方式,数据在不同region server分布得比较均匀。批量读写大小的设置是根据不同大小的响应时间选择的较优的一个值,其中,批量读大小:100,批量写大小:100。

批量读写测试数据如下:

1686714102

完整流程测试数据如下:

1686714112

2)OceanBase测试

OceanBase以表的形式存储字典数据,把key作为主键来保证数据不重复,把value设为自增来保证数据唯一,建表语句如下:

CREATE TABLE `t_olap_realtime_cd_measure_duid_dict` (
  `dict_key` VARCHAR(256) NOT NULL,
  `dict_val` BIGINT(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`dict_key`)
) DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(dict_key) PARTITIONS 10

跟HBase相比,这种方式简化了数据处理流程,只需要写SQL即可完成:

    • 查询已存在的字典值:select dict_key,dict_value from t_olap_realtime_cd_measure_duid_dict where dict_key in (...)
    • 对于上一步结果中不存在的dict_key插入数据库:insert ingore into t_olap_realtime_cd_measure_duid_dict (dict_key) values (...)
    • 对于上一步插入的数据再一次查询数据库:select dict_key,dict_value from t_olap_realtime_cd_measure_duid_dict where dict_key in (...)

使用OceanBase,不需要在代码层面关注key重复和value的唯一自增,都由数据库本身的特性来实现,不仅简化了处理流程,相比单条数据写入,批量写入也更加高效。OceanBase批读写大小分别为:批量读500,批量写:500。

批量读写测试数据如下:

1686714163

完整流程测试数据如下:

1686714172

3) 测试数据分析比较

首先,对比批量读吞吐(单位:条/秒)。

压力HBaseOceanBase
一级83109.45158579.1
二级84355.54264192.8
三级76857.87329107.3

1686714194

根据各存储系统的不同特点,设置了不同的批量查询大小,HBase:100,OceanBase:500。从上图可见,测试压力从一级到三级(数据量在4万到24万之间),OceanBase的查询吞吐量明显比HBase高。

其次,对比批量写吞吐(单位:条/秒)。

压力HBaseOceanBase
一级43256.6249612.5
二级64339.58326436.7
三级77805.46358716.2

1686714222

因为要保证key不重复,HBase需要使用checkAndPut方法进行单次单条数据写入,而OceanBase把key作为主键保证数据不重复,可以单次批量数据写入,每次500条,所以OceanBase的批量写吞吐量比HBase高很多。

再来对比完整流程平均时间(单位:毫秒)。

压力HBaseOceanBase
一级657.52307.45
二级1000.85386.42
三级1279.63474.59

1686714234

从对比数据可知:

  • 在一个完整的数据处理流程时间开销上,OceanBase最低,不到其他两个的50%。
  • 在一个实时任务(4万~8万数据量)的情况下,HBase、OceanBase都能在1秒内完成。
  • 在两个实时任务(8万~16万数据量)的情况下,HBase的处理时间都超过了1秒。但是,因为数据量并不均匀,HBase也没有呈现出明显的延迟。
  • 在三个实时任务(12万~24万数据量)的情况下,HBase的平均时间升高到了1.27秒,实时任务的延迟也越来越大。
  • 随着压力不断增大,只有OceanBase能持续在0.5秒内完成数据处理流程。

最后,对比平均吞吐量(单位:条/秒)。

压力HBaseOceanBase
一级25033.9457429.03
二级33161.5891582.48
三级35500.47112002.3

1686714264

在数据吞吐量上,OceanBase是HBase的2~3倍,并且随着数据量的不断增加,优势越来越大。

不同数据量压测,OceanBase 与HBase表现对比总结

字典服务存储的数据特征是前期读多写多,随着字典数据的不断沉淀,已存在的字典越来越多,后期就是读多写少。本次测试使用的是随机生成的uuid数据,所以整个数据处理流程一直都是全读全写,对存储系统来说,比线上真实环境压力更大。

本次测试的数据量范围是在4万~8万、8万~16万、12万~24万之间波动,通过不断提高实时任务的个数给底层存储系统施加压力,通过观察实时任务的延迟情况来衡量存储系统的处理能力。

    • 在4万~8万数据量情况下,HBase和OceanBase均能在1秒内完成数据处理,不会产生延迟。所以,在4万~8万数据量场景下,HBase和OceanBase都能满足需求。
    • 在8万~16万数据量情况下,HBase在1秒左右完成数据处理,不会产生明显延迟。所以,在8万~16万场景下,HBase和OceanBase都能满足需求。
    • 在12万~24万数据量情况下,HBase的处理时间是1.27秒,随着时间积累,延迟也越来越大。所以,在12万~24万场景下,只有OceanBase能满足需求。
    • 在测试过程中,OceanBase是在数据量28万~56万,且加到了7个实时任务的情况下,才开始出现延迟,数据处理时间1.1秒。

另外,根据测试统计数据,在批量读、批量写、吞吐量上,OceanBase都有明显优势。HBase要保证key不重复和value自增,只能通过单条数据写入,写数据成为了整个数据流程的瓶颈。通过数据库本身的特性,使用OceanBase时不需要关注key重复和value自增的问题,通过SQL批量写入数据,从而能提供更大的写吞吐。

综上,从数据处理能力、资源使用情况和数据处理流程复杂度上,贝壳最后选择OceanBase作为实时字典服务的存储系统。在使用过程中,OceanBase实现了更高的查询性能和稳定性,更低的硬件成本和运维成本,以及更简单的部署。贝壳后续也将在更多合适的场景中推广、应用OceanBase。


OceanBase 云数据库现已支持免费试用,现在申请,体验分布式数据库带来全新体验吧 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982565.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux学习记录(二)-------文件IO

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言文件IO1.函数open2.函数close3.函数lseek4.函数read5.函数write 前言 文件IO Linux 自带的工具&#xff1a;man手册 man 1 是普通的shell命令&#xff0c;比如…

最新CSS3横向菜单的实现

横向菜单 原始代码&#xff1a; <nav class"list1"><ul><li><a href"#">Shirts</a></li><li><a href"#">Pants</a></li><li><a href"#">Dresses</a>…

零基础STM32单片机编程入门(二十五) 内部FLASH模拟EEPROM实战含源码

文章目录 一.概要二.FLASH模拟EEPROM的优势三.FLASH模拟EEPROM的原理四.数据读写步骤五.数据转移流程图六.FLASH模拟EEPROM读写例程七.CubeMX工程源代码下载八.小结 一.概要 STM32F103C8T6是一款强大而灵活的微控制器&#xff0c;它的片内Flash存储器可以用来存储有关数据&…

sqli-labs-php7-master第5-10关

第五关&#xff1a; 根据提示输入ID,随便来个一 输入100&#xff0c;因为数据库没有&#xff0c;所以这里没输出内容 还是先找注入点&#xff1a;输入单引号试试 注入点找到了‘ 查询数据库列数&#xff1b;&#xff1f;id1 order by 4 -- 测试发现order by 3时页面正常&…

C++笔试练习笔记【5】:最小花费爬楼梯(有题目链接) 初识动态规划

文章目录 题目思路代码 动态规划简介**一、什么是动态规划****二、动态规划的应用场景****三、动态规划的基本步骤****四、动态规划的优缺点** 题目 题目链接&#xff1a;https://www.nowcoder.com/practice/9b969a3ec20149e3b870b256ad40844e?tpld230&tpld39751&ru/…

探索人工智能技术的发展导致知识崩溃危险的可能性

概述 本文分析了人工智能&#xff08;AI&#xff09;技术的发展在缩小人类知识库方面的潜力。 作者认为&#xff0c;如果大语言模型&#xff08;LLMs&#xff09;等人工智能技术迅速发展&#xff0c;人工智能生成的内容成为人类接触的大部分信息&#xff0c;那么长尾知识&…

python图表没有正确显示中文,这通常是因为matplotlib的默认设置不支持中文字符,或者相应的字体没有正确加载。

如果图表没有正确显示中文&#xff0c;这通常是因为matplotlib的默认设置不支持中文字符&#xff0c;或者相应的字体没有正确加载。你可以通过指定支持中文的字体来解决这个问题。下面是如何设置matplotlib以确保能够在图表中显示中文的步骤&#xff1a; 方法1&#xff1a;全局…

python的多线程

python的threading模块&#xff0c;它提供了丰富的接口来创建和管理线程。 定义一个函数print_numbers&#xff0c;这个函数将由线程执行。在这个函数中&#xff0c;我们使用一个循环来打印数字&#xff0c;并使用time.sleep(1)来模拟每个数字打印之间有1秒的延迟。 在 if __…

Windows应急响应-排查方式

目录 Windows应急响应排查流程一、账户排查排查方法&#xff08;1&#xff09;查看用户信息&#xff08;2&#xff09;lusrmgr.msc手动查&#xff08;比较麻烦&#xff09;&#xff08;3&#xff09;检测克隆账户 ---可使用安全工具D盾进行检测&#xff0c;同时可以直接查看端口…

群辉NAS利用AList搭建混合云盘⑥挂接腾讯微云

目录 ……接前文 5、挂接腾讯微云 未完待续…… ……接前文 5、挂接腾讯微云 登录AList后台→管理→存储→驱动供选择“腾讯微云”→填写挂接路径 打开“配置文档”(详见前文) 打开配置文档→简体中文→开始→找到腾讯微云部分,可以看到关于Cookie的设置方法。 手工用…

第十二章 元数据管理10分

12.1 引言 如果没有元数据&#xff0c;组织可能根本无法管理其数据。 ISO/IEC11179 元数据注册标准。 元数据管理原则&#xff1a;应归尽归&#xff0c;应收尽收。衡量标准&#xff1a;目录是否完整。&#xff08;去第十二章 元数据管理&#xff09;。 主数据管理&#xff1a;主…

(Javaweb)Ajax,Axios,Vue

目录 一.Ajax 二.Axios 三.前端工程化 四.接口文档的管理平台YAPI 五.Vue项目 六.Vue项目开发流程 一.Ajax 1.通过Ajax从服务器端获取数据 Ajax---JavaScript&#xff08;网页行为&#xff09;XML&#xff08;标记语言--用来存储数据&#xff09; 客户端--浏览器 服务…

【C++】深入理解类和对象(1)

自己打败自己是最可悲的失败&#xff0c;自己战胜自己是最可贵的胜利。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;类的定义 • &#x1f330;1.类定义格式 • &#x1f330;2.访问限定符 • &#x1f330;3.类域 &…

人工智能时代,程序员当如何保持核心竞争力?

目录 前言 一.AI辅助编程对程序员工作的影响 二.程序员应重点发展的核心能力 三.人机协作模式下的职业发展规划 结束语 前言 随着AIGC&#xff08;如chatgpt、midjourney、claude等&#xff09;大语言模型接二连三的涌现&#xff0c;AI辅助编程工具日益普及&#xff0c;程序…

C++第三十一弹---C++继承机制深度剖析(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 1.菱形继承及菱形虚拟继承 1.1 单继承 单继承&#xff1a;一个子类只有一个直接父类时称这个继承关系为单继承。 Student的直接父类是Person&#xff…

双向循环链表和内核链表

目录 双向循环链表 结构设计 初始化 插入 删除 遍历&#xff08;顺序/逆序&#xff0c;打印输出&#xff09; 查找 主函数 内核链表 内核链表初始化定义 内核链表的插入定义 内核链表的遍历定义 内核链表剔除节点定义 内核链表如何移动节点定义 内核链表的应用 临时补充…

身在职场,不得不提防的几个问题,能让少走许多弯路

职场路本就崎岖&#xff0c;如果再走了弯路&#xff0c;脚下的路将会更漫长且难走。 谁不想一帆风顺&#xff0c;可谁又能一帆风顺&#xff1f;不是人心险恶&#xff0c;而是立场本就不同&#xff0c;为了各自的利益考虑无可厚非。 你可以说凭借能力获取利益&#xff0c;为什…

CVE-2023-37569~文件上传【春秋云境靶场渗透】

# 今天我们拿下CVE-2023-37569这个文件上传漏洞# 经过简单账号密码猜测 账号&#xff1a;admin 密码&#xff1a;password# 找到了文件上传的地方# 我们直接给它上传一句话木马并发现上传成功# 上传好木马后&#xff0c;右键上传的木马打开发现上传木马页面# 直接使用蚁剑进行连…

Linux5:Shell编程——函数、重定向

目录 前言 一、函数 1.函数结构 2.函数实例 3.函数传参 二、重定向 1.输出重定向 2.输入重定向 3.同时使用 4.重定向深入了解 5.垃圾桶 总结 前言 Shell编程将会在本章完结 一、函数 1.函数结构 #!/bin/sh # 函数function fun1() {echo "this is a funtion&q…

【有手就行】:从无到有搭建后端SpringBoot项目

前言 想静下心来写点东西&#xff0c;但是确实想不到该写点啥&#xff0c;可能是少了点感觉吧 &#x1f622;。前面刚整理了下前端VUE&#xff0c;就想了下把后端也一起整理下吧&#xff0c;免得换电脑了安装环境又要弄半天&#xff0c;那就开搞吧 首先 准备环境 1.安装IDEA…