作者:禅与计算机程序设计艺术
1.简介
1.微博搜索服务的需求
在社交媒体平台的发展过程中,越来越多的人依赖于微博进行信息的传播、分享。不仅如此,微博作为新浪等知名门户网站的基础服务,有着独特的特性。比如,它是一个高度互联网化的信息流通工具,用户可以自由的发布或转发微博内容,并且具有大量的搜索功能。因此,为微博搜索服务提供更加高效、精准的结果,帮助用户找到想要的内容,也成为各大互联网公司关注的一个重点方向。
在微博搜索服务中,通常会采用基于搜索引擎的关键词匹配方式,通过检索用户输入的关键字,返回包含相关主题信息的微博条目。比如,当用户在微博客户端输入搜索关键字“天气”时,系统将从海量微博内容中返回包含“天气”主题的微博条目,同时显示微博发布者的头像、昵称和微博内容。随着微博的发展,越来越多的应用和网站都依赖微博作为信息来源,实现了信息的快速传播、广泛流动和共享。
但是,为了让微博上的信息查询变得更加高效、准确,搜索引擎需要对微博内容进行分析,提取其中包含的关键信息。而Hbase是一个开源分布式NoSQL数据库,可以用来存储和管理海量结构化数据,其中包括微博数据。通过对HBase微博数据的存储、索引和检索,我们就可以提高微博搜索服务的效率和效果。
本文将通过以下几个方面详细阐述Hbase在微博搜索业务中的应用。
2.HBase基本概念及术语
2.1.什么是HBase?
HBase是一个开源的分布式列存储数据库。它提供类似于BigTable的能力,能够在廉价廉耐的硬件上运行,并支持高吞吐量的随机读写访问。HBase不同于一般的关系型数据库,它不是把数据按行存放,而是按照行键和列族的方式存放。列族是HBase的一种重要特性,它允许用户指定哪些列属于同一个列族,可以有效地压缩数据,减少磁盘空间的占用。列族也使HBase具备了与其他NoSQL数据库不同的特性。
2.2.HBase与BigTable比较
Bigtable是谷歌开发的列存数据库,相比于HBase来说,它在很多方面都存在差距。首先,Bigtable是构建在Google File System(GFS)之上的,它使用传统的Google文件系统(GFS)存储数据,也就是说它的部署方式和实现方式较为复杂。其次,Bigtable的容错机制较弱,它只能靠备份恢复数据,而且如果某些节点宕机的话,整个集群也就宕机了。另外,Bigtable的数据模型设计也比较简单,主要是以Rowkey-ColumnFamily-Timestamp三元组组织数据。第三,由于Bigtable是面向稀疏数据的,所以它的性能优化主要靠手动调优,不够自动化。最后,Bigtable还没有开源,而且现在已经被Apache基金会收购。
总的来说,Bigtable虽然强大且功能丰富,但它缺乏开源、自动化调优和社区力量支持等诸多弊端。HBase则不同,它开源、自动化、支持社区力量,提供了可靠的、高效的、可伸缩的解决方案。
2.3.HBase的数据模型
HBase的数据模型中,最重要的是Cell(单元格),它就是我们熟悉的表格中的单元格。每个Cell由RowKey(行键)、ColumnFamily(列族)、ColumnName(列名称)、TimeStamp(时间戳)四个部分构成。其中,RowKey是唯一标识一行的主键,在HBase中,每个Cell只能有一个RowKey。ColumnFamily是由多个列组合而成的集合,在这一列族内,相同的ColumnName代表的是相同的值。举个例子,在一个博客网站上,每篇博文可以看作是一个RowKey,而文章的作者、发布日期、阅读量、评论等多个列可以看作是ColumnFamily。这样,我们就能够根据RowKey快速检索到文章的所有相关信息。
2.4.HBase的分片策略
HBase数据通过RegionServer进行分片。默认情况下,HBase将一个表切割成128个Region,每个Region都会包含一些连续的RowKey范围。当我们插入一条数据时,HBase会确定该条目的落入哪个Region,然后再将该条目写入相应的Region中。当我们需要检索某个范围的数据时,HBase会根据查询条件计算出所需Region的列表,然后分别读取这些Region中的数据,并合并最终的结果。分片策略决定了查询的效率和资源利用率。
2.5.HBase的连接器
HBase可以通过Thrift、RESTful API或者Java客户端访问。Thrift是HBase官方推荐使用的接口,可以跨语言调用。RESTful API只读模式,用于Web后台和移动客户端的查询。Java客户端是HBase的官方API,能够实现各种复杂功能。
3.HBase搜索原理及工作流程
3.1.索引建设
在搜索引擎中,索引建设是指将大量的文本、图像、视频、音频、结构化数据等信息转换为搜索引擎能够处理的形式。目前主流的搜索引擎都是基于关键词匹配的,而微博中的文本内容比较复杂,需要进行分词、去停用词等操作才能提取关键信息,因此需要对微博数据建立索引。
HBase作为一个分布式列存储数据库,不需要单独的索引建设过程,它本身就可以满足搜索需求。HBase的数据模型直接映射到搜索引擎的倒排索引模型,不需要额外的建模操作,就可以方便的通过反向查询法快速检索到任意一段内容。
3.2.微博搜索流程
当用户输入搜索关键字时,系统会对搜索词进行分词、去停用词等操作,生成包含所有关键词的查询语句。HBase会根据查询条件计算出所需Region的列表,然后分别读取这些Region中的数据,并合并最终的结果。如下图所示:
- 用户输入搜索关键字“武汉”,请求搜索服务;
- 搜索服务接收请求,解析关键字“武汉”;
- 将关键字“武汉”解析后,生成对应的查询语句;
- 查询语句发送给HMaster,获取所有相关Region的位置信息;
- 根据Region位置信息,搜索服务连接到相应的RegionServer,获取对应的数据;
- 数据经过网络传输后,合并排序得到最终的搜索结果;
- 返回搜索结果给用户。
通过以上步骤,微博搜索服务完成了数据的检索,并通过HBase的搜索机制,将用户的查询结果进行过滤、排序、分页等处理,提升了用户的体验。
3.3.微博搜索索引更新
HBase在微博搜索业务中的应用还带来了一个新的问题,即索引更新。由于用户不断地上传微博数据,因此索引库中的数据也会越来越老旧。搜索引擎需要定期对索引库进行清理,保证数据的最新性。而HBase提供了一种分布式的索引更新机制,只要在HBase中插入、删除或修改了数据,相应的索引记录就会同时更新。搜索引擎只需要定期扫描索引库即可,就可以获得最新的数据。
4.HBase在微博搜索业务中的应用案例
4.1.安装配置
4.1.1 安装Hadoop、Zookeeper
Hadoop、Zookeeper可以从官网下载安装包进行安装。如果本地没有安装,可以使用远程主机来进行安装。
4.1.2 配置环境变量
修改hadoop的配置文件etc/hadoop/core-site.xml
,加入以下配置信息:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>hbase.rootdir</name>
<value>file:///data/hbase</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>localhost</value>
</property>
</configuration>
配置说明:
-
fs.defaultFS
表示HDFS的地址,如果使用远程主机,需要改为hdfs://{主机IP}:9000
。 -
hbase.rootdir
表示HBase的根目录,这里设置为本地文件系统,路径填写到你的实际存储路径,比如:/data/hbase
。 -
hbase.zookeeper.quorum
表示Zookeeper的地址,这里填写到你的本地服务器的IP地址,通常为localhost
。
4.1.3 创建HBase的库表
可以通过SSH登录到你的服务器,输入以下命令创建一个HBase的库表:
hbase shell
create 'weibo_search', {NAME => 'info', VERSIONS=> 1}
disable 'weibo_search'
alter 'weibo_search', {METHOD => 'append', NAME=>'info'}
enable 'weibo_search'
命令说明:
-
create 'weibo_search'
创建一个名为weibo_search
的库表。 -
{NAME => 'info', VERSIONS=> 1}
在weibo_search
库表下创建了一个名为info
的列簇,版本数量为1。 -
disable 'weibo_search'
关闭weibo_search
库表的写权限。 -
alter 'weibo_search', {METHOD => 'append', NAME=>'info'}
开启info
列簇的追加写权限。 -
enable 'weibo_search'
打开weibo_search
库表的写权限。
执行完毕后,输入exit
退出HBase的shell界面。
4.2.导入数据
有两种方法可以导入微博数据到HBase中。第一种方法是离线导入,即把所有的微博数据导出,然后导入到HBase中。第二种方法是实时导入,即在接收到新微博时,就导入到HBase中。
4.2.1 离线导入
如果所有微博数据已经存放在HDFS上,那么可以使用以下命令导入到HBase中:
hdfs dfs -text file:/path/to/weibodata | hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator=' ' weibo_search info
命令说明:
- hdfs dfs -text file:/path/to/weibodata
将HDFS上微博数据转存为文本文件,并将其所在路径传递给ImportTsv
命令。
-
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv
导入文本文件的命令。 -
-Dimporttsv.separator=' '
设置分隔符为 -
weibo_search info
指定导入的库表名称和列簇名称。
4.2.2 实时导入
如果新微博实时推送到Kafka,可以借助Flume对数据进行收集、解析、加载。Flume是Cloudera开源的一款分布式日志采集、聚合、路由的框架。我们可以搭建好Flume的收集、解析、写入功能后,把实时的微博数据推送到Kafka中,然后使用以下命令导入到HBase中:
flume-ng agent --conf /path/to/flume.conf -f /path/to/log.conf
kafka-run-class.sh kafka.tools.ConsoleProducer --broker-list localhost:9092 --topic topicName
命令说明:
-
flume-ng agent
启动Flume Agent。 -
--conf /path/to/flume.conf
指定Flume配置文件路径。 -
-f /path/to/log.conf
指定日志采集规则配置文件路径。 -
kafka-run-class.sh kafka.tools.ConsoleProducer
启动Kafka Producer命令行客户端。 -
--broker-list localhost:9092
指定Kafka Broker的地址。 -
--topic topicName
指定Kafka Topic名称。 - 在命令行窗口输入微博数据内容,Flume会自动把数据推送到Kafka中,导入到HBase中。
执行完毕后,输入ctrl+c
退出Flume和Kafka命令行客户端。
4.3.检索数据
4.3.1 全文检索
通过HBase的索引功能,我们可以快速检索到符合用户搜索条件的微博内容。完整的检索语法如下:
SELECT * FROM "weibo_search"."info" WHERE ROWKEY LIKE '%keyword%' AND COLUMN1 = 'value' ORDER BY TIMESTAMP DESC LIMIT num
命令说明:
-
SELECT * FROM "weibo_search"."info"
从weibo_search
库表的info
列簇中检索所有数据。 -
ROWKEY LIKE '%keyword%'
搜索关键字中包含keyword
的微博。 -
COLUMN1 = 'value'
指定列值。 -
ORDER BY TIMESTAMP DESC
按照时间戳倒序排序。 -
LIMIT num
限制返回条数。
使用命令行执行全文检索:
hbase shell
scan 'weibo_search'
命令说明:
-
scan 'weibo_search'
查看weibo_search
库表的所有数据。
4.3.2 精准检索
在微博搜索业务中,我们可能需要根据特定的维度,比如发布者、地域等来过滤微博内容。这种情况下,我们无法使用全文检索,只能采用精准检索。在HBase中,我们需要定义多个列族,每个列族对应一种搜索维度,例如:
CREATE ‘weibo_search’,
{NAME => 'publishTime', BLOOMFILTER => true},
{NAME => 'publisherId'},
{NAME => 'location'},
{NAME => 'content'}
命令说明:
- CREATE 'weibo_search'
创建一个名为weibo_search
的库表。文章来源:https://uudwc.com/A/Lap52
-
{NAME => 'publishTime', BLOOMFILTER => true}
在weibo_search
库表下创建了一个名为publishTime
的列簇,并开启BloomFilter。 -
{NAME => 'publisherId'}
在weibo_search
库表下创建了一个名为publisherId
的列簇。 -
{NAME => 'location'}
在weibo_search
库表下创建了一个名为location
的列簇。 -
{NAME => 'content'}
在weibo_search
库表下创建了一个名为content
的列簇。
假设我们要查询发布时间大于等于2018年1月1日的微博,并且发布者ID为1000的微博,那么可以执行以下命令:
hbase shell
set 'weibo_search'.'info:publishTime','20180101'
set 'weibo_search'.'info:publisherId','1000'
scan 'weibo_search'
命令说明:文章来源地址https://uudwc.com/A/Lap52
-
set 'weibo_search'.'info:publishTime','20180101'
将搜索条件publishTime >= 20180101
添加到HBase缓存。 -
set 'weibo_search'.'info:publisherId','1000'
将搜索条件publisherId = 1000
添加到HBase缓存。 -
scan 'weibo_search'
查看weibo_search
库表的所有数据,同时过滤出符合搜索条件的微博。
通过精准检索,我们可以大幅提高微博搜索服务的响应速度,从而为用户提供更加准确和迅速的搜索结果。