大数据技术在智慧旅游行业的应用之算法层、存储层、Hadoop集群、实时计算方面等角度分析探讨

浏览: 3620

同程吴文波

大家好,我是Bob wu,在天善的论坛里面是叫Bob,目前是在同程旅游工作,非常感谢梁总和吕总给了我这次与大家交流学习的机会。

请大家多多关注并支持我们:

商业智能问答社区 : http://www.flybi.net 

商业智能学院 : http://www.hellobi.com 

商业智能招聘平台 : http://www.bijob.cn

天善官网 : http://www.tianshansoft.com 

天善智能大数据交流群 :225978231 加群请注明: 天善智能

我和天善智能的老梁是认识很久的网友,大家都是做BI方面的,在数据方面有共同的兴趣。刚刚推荐应用方面我们途牛的育峰已经给大家讲的很详细了,我只搞技术的,今天给大家分享在项目开发过程中的一些问题。

预计能收获的点:

1  Hadoop&hbase集群的一些坑可以知晓下
2 集群程序的简单构建

本次的目的是一起交流学习,在这个方面,我只是一个新人。如有错误,请大家多多关照,多多包涵。

在大数据方面我们只是刚刚起步,一直是在参考外界的做法,内部摸索着前行。每家的情况都不相同。我们当初只是想解决一个痛点,从而构建了Hadoop集群。

同程在12和13年一直是专注于PC方面,在SEM、竞价等方面做的比较好,网站的流量很可观。一方面,公司也期望这些流量能有很好的发挥;另外一方面,网站也想提升下用户体验。但是当时还有很多的搜索无结果页等空白页面,这在宝贵的网站页面上是一种浪费。在这种背景下,很多的产品人员都找到数据部门,期望能从数据的角度为访问者提供更好的资源。我们当时在承接这种推荐系统时,手头只有sqlserver机器,普通的服务器资源等,面对几百G的用户行为数据,使用关联规则,基于人的协同过滤等算法,真心没法计算。

虽然很困难,但是只能上。我们在多方学习摸索以后,初步设计了一些简单的架构:

算法层:

1.       使用R语言来完成算法模型的建立

2.       使用Mahout、MapReduce来完成简单算法的变现。

3.       尝试使用过RHadoop的结合。

存储层:

1.       离线计算方面则使用Hadoop做为分布式存储的主集群。这样的目的是能存储更多的用户消费数据,并提供足够的硬件资源,为每天离线算法的完成做好准备。

2.       实时查询层的存储则使用HBase作为主集群。因为推荐系统的接口都是固定场景的查询。这样非常适合HBase的表设计。

接口程序层:

3.       对外接口程序主要的作用是承担网站的推荐模块调用。这个接口使用java编程,访问HBase并输出json格式的数据。

4.       接口查询日志记录程序。对外接口每次收到查询请求时,会记录下请求参数和响应输出参数。这些log是不能影响到对外接口的性能。所以我们采用异步的方式提交到消息队列中。日志的记录数是请求并发量的几十倍,所以我们需要比较好的消息队列来支撑,所以选择使用kafka。

5.       日志入库程序。接口产生的日志在进入消息队列以后,会有独立的后台程序定时从队列中消费数据,并插入到HBase中。这些日志插入到hbase的目的是为了分析算法的好坏。

6.       离线数据更新程序。承担离线计算的Hadoop集群数据需要更新,所以我们使用java调用Sqoop的API 来完成数据的同步工作。这个程序中会涉及到依赖的问题。

7.       实时查询层的数据更新程序。旅游行业中一些资源是具有时效性的,例如酒店。如果某个酒店在当天有热门事件导致满房,我们是需要下线这个推荐资源的。但是这些资源有很多独特的情况,例如酒店受实时政策的影响非常大,而国际机票则没有现成的资源库。我们在这种情况下分了几个步骤来解决。如果有资源库且是sqlserver的,则使用CDC技术进行分钟级别的更新;如果是mysql的,则使用flume来收集日志实时更新;如存在mongodb上,则需要开发程序来实现同步;如果没有资源库的,则接入项目的查询接口。通过用户的查询,异步提交数据到消息队列,进而入HBase中。

8.     推荐日志分析程序。日志如果需要实时分析和统计,则可通过HBase的Api来做到。我们只需要编写java代码访问即可。如果是每天离线统计效果,则此时需要启用HBase的协处理器功能。

通过以上的程序分解,简单版本的推荐系统如期上线。在这个过程中,我们解决了很多问题,在Hadoop、HBase、kafka等大数据生态组件的使用上更加熟练了。
      
这一阶段会让一个人受益良多。首先,这是一个真实的项目上线。在实战中收获的技能远比看书的效果好。在此稍微总结下一些问题:

Hadoop集群

Hadoop确实非常优秀,容错性很好。有机器宕机了都没问题。但是在使用Hadoop时,经常遇到的问题是内存错误。Hadoop0.23以前的版本中主要是tasktracker 、jobtracker等进程遇到内存错误;hadoop2.0以后则是resourcemanager、ApplicationMaster、container、nodemanager、虚拟内存之间的内存配置问题。其实这些需要深入了解架构图,并且不断地跑不同任务,不断地总结才能有收获。其次的一个问题是版本升级问题。我们使用CDH版本,从CDH3、CDH4到CDH5,这其中升级了好几次,各种各样的方式都尝试过。例如按hadoop自带的升级命令进行等,失败过多次。

在遇到此类问题时,大家记得多去看每个进程的日志文件。在充分理解架构流程图以后,你在分析日志时将会很快速地定位问题。

另外熟悉源代码也是非常关键的。因为hadoop可以支持debug模式日志输出,日志将会变得更加详细。如果详细阅读了源代码,能帮你加深对架构图的理解,也能加深方法之间的调用关系。

在升级版本时切记一定要保留数据到磁盘中。防止出现灾难。

HBase集群是我们的一个非常重要的集群,很多对外提供实时查询的接口都是依赖HBase。在使用过程中也是有很多的问题。

hbase表设计问题。这个是很常见的。在实际场景中,我们不仅仅是按照rowkey来查询,还需要按照列名过滤。例如为100个会员查询前10个最优的资源。在这个情况下,memberid是rowkey,算法为每个会员自动生成1000个最优资源和产品,列名称可使用产品+0001开始。我们在查询的时候就可以同时使用rowkey和列名称过滤。因为列名称是字符串,所以产品0001、产品0002。。。。。。这些列是默认排序好的。不同的产品则包含不同的列。

HBase 数据存储问题。如果某个表数据存储过大,则会一边写入,一边进行split,一边进行GC。这就可能导致region出现超时等错误。所以为了保险起见,每个表在创建之前就要进行预分割操作,rowkey也要进行散列。这样做的目的是让多个region上尽可能分布均匀的数据,共同承担来自前端的并发查询。散列推荐使用MD5,预分割则遵循16,32这样的规则。

HBase GC的配置。HBase中不可避免的一个事情就是gc。在gc内存占比,时间等方面要详细考虑。GCT/FGC/YGC 是有一定的关联关系,在不同的集群硬件环境中,要多加测试,从实验中选择一个合理的参数。这些实验都需要依赖hbase-env.sh中的jvm参数配置。

HBase中内存配置。这些参数来自hbase-site.xml文件中。分别涉及到缓存大小、读写内存占比等。在实际的生产环境中也是需要进行多次测试,选择合适的配置值。

HBase表优化工作。这些涉及到写入优化、查询优化等。查询优化方面则要考虑regionserver的cache、Max Version、TTL配置、StoreFile配置大小;写的方面要考虑AutoFlush、WriteBuffer、WAL Flag。如果是海量数据写入,建议使用MapReduce生成HFiles,并通过LoadIncrementalHFiles 方式来载入到HBase表中。

以上内容是我在推进项目中的一些总结。但是程序总是需要迭代的,例如推荐算法需要更高的时效性:用户购买完成后就实时计算并输出结果等;算法要讲究复用性;要满足移动互联网的LBS特性。

实时计算方面

:我们在离线算法集群和实时查询层之间构建了一个实时计算集群。这主要是使用Spark来搭建的。

1       使用Spark改造原有的离线算法,并全部移植到spark中。

2       使用spark-stream来读取实时消息队列数据,并实时计算部分算法。

3       Spark计算结果完成后直接写入HBase集群

这样做的效果是可以将原来非常耗时的算法变为几个小时执行的单元;可以接收用户的实时数据,并实时计算部分小算法来完成实时推荐的效果。

同程有7亿以上的下载量。在移动互联网时代,基于LBS的一些应用是必不可少的。

我们在LBS上也有些尝试。就拿客户端上距离您最近的**资源来讲。用户在打开的时候会传入经纬度数据,但是用户也可能是在运动的状态中。如何快速检索距离用户最近的资源数据是一个问题。但是我们的查询层是HBase,没法根据经纬度的范围进行Rowkey扫描。当时为了解决这个问题,我们想了一个方案:

1.       使用0.5*0.5的小方格(单位:千米),将全国分解为n多个区域块。每个区域块定时更新最佳资源、最近资源、个性化资源等。

2.       使用Apache的GEOHASH算法,将这个范围内的经纬度都hash为一个字符串。并使用这个字符串作为rowkey进行存储。

3.     前端传入的经纬度也使用GEOHASH算法转换为字符串。

这样做,能让HBase集群承担高并发的LBS查询任务,但是总归是有些误差。唯一不足的地方在于:查询HBASE是使用rowkey的前缀进行查询。这多少会牺牲些性能。在个性化推荐的前提下,这个方案勉强适用。如果公司资源比较少,也不需要包含一些个性化算法结果的话,那直接使用数据库的经纬度字段索引、使用redis缓存也都是比较好的方式。

我的分享就到此为止,欢迎大家批评指正。

推荐 0
本文由 天善智能 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册