)
十四、HBase 数据库设计之 RowKey第2关车联网 RowKey 设计任务描述本关任务车联网 RowKey 设计与查询某辆车在某个时间范围的交易记录。相关知识为了完成本关任务你需要掌握如何避免热点问题。场景模拟车联网监控系统系统由车载硬件设备、云服务端构成。车载硬件设备会定时采集车辆的各种状态信息并通过移动网络上传到服务器端。服务器端接收到硬件设备发送的数据首先需要将数据进行解析校验随后会将该消息转发到国家汽车监测平台和地方汽车监测平台最后将解析后的明文数据和原始报文数据存储到系统中。车辆的数据和其他数据需要通过 Web 页面或 Rest API 接口进行查询访问。要求半年内的数据查询响应时间在毫秒级别内超过半年的数据需要放到更加低成本的介质上查询延迟在 3s 以内这些数据的查询频次比较低。系统的主要参数有以下几项:1.10万台车辆同时在线2.车辆正常情况下平均每分钟发送两个数据报文到监控平台3.若车辆处于报警状态则平均一秒钟发送一次数据报文4.数据情况1车辆数据报文平均大小为1KB2解析后的数据包大小为7KB3平均一台车每天会产生20MB的数据4同时系统有2.9亿行的数据需要写入到数据库中初期的 RowKey 的格式为车辆ID“-”时间戳。初期的部分 Rowkey 如下001-1516195465002-1516195555003-1516195555004-1561585623005-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 459460515112375 1515314924 429413515112375 1515363367 763363515112375 1515472993 399274515112375 1515678778 877876515112375 1516195465 564591615112375 1516206693 396602615112375 1516417717 717714615112375 1516571214 412175615112375 1517324315 513423715112375 1517702149 941207715112375 1518088216 612880815112375 1518093870 078390815112375 1518413486 684314815112375 1518541784 487145815112375 1518967628 826769815112375 1519094744 447490915112375 1519948703 307849915112375 1520023763 367320025112375 1520539421 124935025112375 1520820749 947028025112375 1521308196 691803125112375 1521697722 227796125112375 1522136442 2446312251查询说明查询车辆编号为 12375 在是时间 1515064954 到 1515363367 中的交易记录预期输出key:2609a-12375-1515314924 value:4294135151key:2609a-12375-1515064954 value:4594605151key:2609a-12375-1515363367 value:7633635151开始你的任务吧祝你成功答案见《头歌实践教学平台大数据存储2023十四下答案》有任何问题都可以随时关注私信