头歌实践教学平台:大数据存储2023(十四下)
2026/8/31 21:55:48 网站建设 项目流程

十四、HBase 数据库设计之 RowKey

第2关:车联网 RowKey 设计

任务描述
本关任务:车联网 RowKey 设计与查询某辆车在某个时间范围的交易记录。

相关知识
为了完成本关任务,你需要掌握:如何避免热点问题。

场景模拟
车联网监控系统,系统由车载硬件设备、云服务端构成。车载硬件设备会定时采集车辆的各种状态信息,并通过移动网络上传到服务器端。服务器端接收到硬件设备发送的数据首先需要将数据进行解析,校验,随后会将该消息转发到国家汽车监测平台和地方汽车监测平台,最后将解析后的明文数据和原始报文数据存储到系统中。车辆的数据和其他数据需要通过 Web 页面或 Rest API 接口进行查询访问。要求半年内的数据查询响应时间在毫秒级别内,超过半年的数据需要放到更加低成本的介质上,查询延迟在 3s 以内,这些数据的查询频次比较低。系统的主要参数有以下几项:

1.10万台车辆同时在线;

2.车辆正常情况下平均每分钟发送两个数据报文到监控平台;

3.若车辆处于报警状态,则平均一秒钟发送一次数据报文;

4.数据情况:
(1)车辆数据报文平均大小为1KB;
(2)解析后的数据包大小为7KB;
(3)平均一台车每天会产生20MB的数据;
(4)同时系统有2.9亿行的数据需要写入到数据库中;

初期的 RowKey 的格式为:车辆ID+“-”+时间戳。
初期的部分 Rowkey 如下:

001-1516195465
002-1516195555
003-1516195555
004-1561585623
005-1568569999
系统运行的初期,数量并不是很庞大的时候,系统并没有产生任何问题,在业务上,比如说“查询车辆ID为001在某段时间内的日志记录”,这种需求毫无压力。但是随着数据量的急剧增加,车辆的活跃度也有翻天覆地的变化,有些车辆极度活跃,该车辆的日志数据也增多了,随其车辆报警的次数也变多了,在开发者的角度来看,这样的车辆查询次数也变多了。由于 RowKey 是字典顺序排序的,这样就会产生这样的一种情况:大量的活跃车辆正好处于一个 Region 上。当大量的用户集中访问同一个 Region 时,Region 所在的单个机器有超出自身承受能力的可能,超出承受能力的时候,节点就宕机了。

初期这种 RowKey 设计不是很合理,产生了一个致命的缺点,HBase 的热点问题,你作为一名 HBase 数据库工程师,你需要对此提出解决方案,你会怎么做呢?

HBase 中的热点现象
Hbase 中的行是按照 RowKey 的字典顺序排序的,这种设计优化了 scan 操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于 scan 。然而糟糕的 RowKey 设计是热点的源头。 热点发生在大量的 client 直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量的 client 访问会使热点 Region 所在的单个机器超出自身承受能力,引起性能下降甚至 Region 不可用,这也会影响同一个 RegionServer 上的其他 Region ,由于主机无法服务其他 Region 的请求。 设计良好的数据访问模式以使集群被充分,均衡的利用。为了避免写热点,设计 RowKey 使得不同行在同一个 Region ,但是在更多数据情况下,数据应该被写入集群的多个 Region ,而不是一个。

避免热点的方法
预分区
预分区一开始就预建好了一部分 Region ,这些 Region 都维护着自己的 start-end keys,在配合上随机散列,写数据能均衡的命中这些预建的 Region

加盐
这里所说的加盐不是密码学中的加盐,而是在 RowKey 的前面增加随机数,具体就是给 RowKey 分配一个随机前缀以使得它和之前的 RowKey 的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的 RowKey 的数量一致。加盐之后的 RowKey 就会根据随机生成的前缀分散到各个 RowKey 上,以避免热点。

哈希
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的 RowKey ,可以使用get 操作准确获取某一个行数据

hash 就是 RowKey 前面由一串随机字符串组成,随机字符串生成方式可以由 SHA 或者 MD5 方式生成,只要 Region 所管理的 start-end keys 范围比较随机,那么就可以解决写热点问题

反转
反转固定长度或者数字格式的 RowKey 。这样可以使得 RowKey 中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机 RowKey ,但是牺牲了 RowKey 的有序性。反转 RowKey 的例子以手机号为 RowKey ,可以将手机号反转后的字符串作为 RowKey ,这样的就避免了以手机号那样比较固定开头导致热点问题

时间戳反转
一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为 RowKey 的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp追加到 key 的末尾,例如 [key][reverse_timestamp] ,[key] 的最新值可以通过 scan [key] 获得 [key] 的第一条记录,因为 Hbase 中 RowKey 是有序的,第一条记录是最后录入的数据。

编程要求
根据提示,在右侧编辑器补充代码,完成以下需求:

使用 hash 避免热点问题 --> 前缀:prefix = substr(md5(uid),0 ,5)
查询某辆车在某个时间范围的交易记录


测试说明
数据说明

车辆ID 时间戳 交易记录编号
12375 1515064954 4594605151
12375 1515314924 4294135151
12375 1515363367 7633635151
12375 1515472993 3992745151
12375 1515678778 8778765151
12375 1516195465 5645916151
12375 1516206693 3966026151
12375 1516417717 7177146151
12375 1516571214 4121756151
12375 1517324315 5134237151
12375 1517702149 9412077151
12375 1518088216 6128808151
12375 1518093870 0783908151
12375 1518413486 6843148151
12375 1518541784 4871458151
12375 1518967628 8267698151
12375 1519094744 4474909151
12375 1519948703 3078499151
12375 1520023763 3673200251
12375 1520539421 1249350251
12375 1520820749 9470280251
12375 1521308196 6918031251
12375 1521697722 2277961251
12375 1522136442 2446312251
查询说明

查询车辆编号为 12375 在是时间 1515064954 到 1515363367 中的交易记录

预期输出

key:2609a-12375-1515314924 value:4294135151
key:2609a-12375-1515064954 value:4594605151
key:2609a-12375-1515363367 value:7633635151
开始你的任务吧,祝你成功!

答案见《头歌实践教学平台:大数据存储2023(十四下答案)》

有任何问题都可以随时关注私信!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询