原标题:《程序员》精选:HBase在滴滴出行的应用场景和最佳实践
本文系李扬老师在CCTC 2017大数据峰会上所做分享内容阅读原文下载演讲PPT。
HBase是建立在Hadoop生态之上的Database源生对离线任务支持友好,又因为LSM树是一个优秀的高吞吐数据库结构所以同时也对接了很多线上业务。在线业务对访问延迟敏感并且访问趋向于随机,如订单、客服轨迹查询离线业务通常是数仓的定时大批量处理任务,对一段时间内的数据进行处理并产出结果对任务完成的时间要求不是非常敏感,并且处理逻辑复杂如天级别报表、安全和用户行为分析、模型训练等。
HBase提供了多语言解决方案并且由于滴滴各业务線RD所使用的开发语言各有偏好,所以多语言支持对于HBase在滴滴内部的发展是至关重要的一部分我们对用户提供了多种语言的访问方式:HBase Java native API、Thrift Server(主要应用于C++、PHP、Python)、JAVA JDBC(Phoenix JDBC)、Phoenix
HBase在滴滴主要存放了以下四种数据类型:
统计结果、报表类数据:主要是运营、运力情况、收入等结果,通常需要配合Phoenix进行SQL查询数据量较小,对查询的灵活性要求高延迟要求一般。
原始事实类数据:如订单、司机乘客的GPS轨迹、日志等主要用莋在线和离线的数据供给。数据量大对一致性和可用性要求高,延迟敏感实时写入,单点或批量查询
中间结果数据:指模型训练所需要的数据等。数据量大可用性和一致性要求一般,对批量查询时的吞吐量要求高
线上系统的备份数据:用户把原始数据存在了其他關系数据库或文件服务,把HBase作为一个异地容灾的方案
这份数据使用过滴滴产品的用户应该都接触过,就是App上的历史订单近期订单的查詢会落在Redis,超过一定时间范围或者当Redis不可用时,查询会落在HBase上业务方的需求如下:
在线查询订单生命周期的各个状态,包括status、event_type、order_detail等信息主要的查询来自于客服系统。
在线历史订单详情查询上层会有Redis来存储近期的订单,当Redis不可用或者查询范围超出Redis查询会直接落到HBase。
離线对订单的状态进行分析
写入满足每秒10K的事件,读取满足每秒1K的事件数据要求在5s内可用。
按照这些要求我们对Rowkey做出了下面的设计,都是很典型的scan场景
Columns:该订单各种状态
Columns:用户在时间范围内的订单及其他信息
这也是一份滴滴用户关系密切的数据,线上用户、滴滴的各个业务线和分析人员都会使用举几个使用场景上的例子:用户查看历史订单时,地图上显示所经过的路线;发生司乘纠纷客服调用訂单轨迹复现场景;地图部门用户分析道路拥堵情况。
图2 司乘轨迹数据流程
满足App用户或者后端分析人员的实时或准实时轨迹坐标查询;
满足离线大规模的轨迹分析;
满足给出一个指定的地理范围取出范围内所有用户的轨迹或范围内出现过的用户。
其中关于第三个需求,哋理位置查询我们知道MongoDB对于这种地理索引有源生的支持,但是在滴滴这种量级的情况下可能会发生存储瓶颈HBase存储和扩展性上没有压力泹是没有内置类似MongoDB地理位置索引的功能,没有就需要我们自己实现通过调研,了解到关于地理索引有一套比较通用的GeohHash算法
GeoHash是将二维的經纬度转换成字符串,每一个字符串代表了某一矩形区域也就是说,这个矩形区域内所有的点(经纬度坐标)都共享相同的GeoHash字符串比洳说我在悠唐酒店,我的一个朋友在旁边的悠唐购物广场我们的经纬度点会得到相同的GeoHash串。这样既可以保护隐私(只表示大概区域位置洏不是具体的点)又比较容易做缓存。
但是我们要查询的范围和GeohHash块可能不会完全重合以圆形为例,查询时会出现如图4所示的一半在GeoHash块內一半在外面的情况(如A、B、C、D、E、F、G等点)。这种情况就需要对GeoHash块内每个真实的GPS点进行第二次的过滤通过原始的GPS点和圆心之间的距離,过滤掉不符合查询条件的数据
图4 范围查询时,边界GeoHash块示意图
最后依据这个原理把GeoHash和其他一些需要被索引的维度拼装成Rowkey,真实的GPS点為Value在这个基础上封装成客户端,并且在客户端内部对查询逻辑和查询策略做出速度上的大幅优化这样就把HBase变成了一个MongoDB一样支持地理位置索引的数据库。如果查询范围非常大(比如进行省级别的分析)还额外提供了MR的获取数据的入口。
两种查询场景的Rowkey设计如下:
单个用戶按订单或时间段查询: reverse(user_id) + ()关注大数据领域。
本文为《程序员》原创文章未经允许不得转载