· 更多精彩内容,请下载阅读全本《Elastic Stack实战手册》
创作人:王欢
审稿人:杨振涛
业务背景
网络舆情监测,主要是利用互联网信息采集技术,以及自然语言处理等智能信息处理技术,通过对互联网公开数据进行自动化抓取,然后对信息进行结构化、自动分类、文本聚类、主题发现与跟踪等,提供信息检索、多维度统计、敏感信息预警、信息简报、自动化报告等功能,帮助用户及时发现危害品牌形象的观点,并为用户分析关注对象在网络中的形象提供依据。
在舆情 SAAS 系统(以下简称:舆情系统)中,用户设置关注的关键词,就可以快速检索对应的舆情数据,以及对提及关键词的数据提供统计图表,包括舆情走势、词云图、情感分布、情绪走势等。
这里的信息检索与统计,都离不开 Elasticsearch(以下简称:ES)的 Query 以及 aggregation功能,下面详细介绍如何使用 Elasticsearch 实现这些功能,以及在实践过程中遇到的一些问题及解决方案。
舆情系统多维度检索
索引设计
采集的数据源包括微博、微信、新闻网页、论坛、自媒体平台、短视频等平台的数据,每天新增去重数据量在 1亿+,每条数据在经过结构化,以及经过 NLP(自然语言处理)之后,超过150 个字段,比如,文章标题、发布时间、发布作者、发布平台、新闻分类、新闻提及地域、新闻情绪等。由于业务端需要对这些数据进行实时检索,对不同平台的数据实时聚合,各平台的数据量分布也有很大的差异,所以按照平台进行拆分,而不是把所有的数据放到一个大的索引里面。
由于不同平台的数据量差异很大,一般地,微博占每日总采集量的 80%,而新闻网页、微信、自媒体平台的占比相对较少。为了避免由于索引的大小不一样,导致每个shard的差异过大,最终导致落在不同节点上 shard 占用空间分布不均匀而出现数据倾斜。
所以,在实现上对微博的索引按照日期做了进一步拆分,微博每日一个索引,而自媒体平台每月一个索引。
索引划分示意图
为了方便业务检索,对按天分索引的微博设置别名,比如 alias weibo_202101
对应weibo_20210101,weibo_20210102,...,weibo_20210131
分词器设计
索引膨胀对比
不同于英文分词器,大部分使用空格作为分隔符。针对不同的检索场景,中文有更多的分词器可供选择,不同中文分词器的选择,会有索引大小,检索性能,以及检索数据的召回率与准确率上的不同。
不同分词器的磁盘占用对比
在同样的数据条件下,通过对不同分词器下索引占用磁盘空间对比,我们发现:
- IK(ik_max_word)分词器,占用磁盘空间最小
- Standard分词器,与 ik_max_word 相差不大,比 ik_max_word 分词方式只增加了 5% 左右
- N-gram 占用空间比较大,相对于 ik_max_word, 当 n=3,4,5 时,占用空间,分别是ik_max_word 的 2倍、3倍、4倍 左右。
检索性能对比
不同分词器的检索耗时对比
在同样的数据条件下,通过对不同的分词下检索性能的对比,我们发现:
- IK(ik_max_word)分词器,检索性能是 standard 分词器的 2-3倍 左右
- N-gram(n=5)分词器,检索性能是 standard 分词器的 7倍 左右,是 ik_max_word 分词器的 3倍 左右
通过综合对比,虽然 n-gram(n=5)分词器具备更高的检索性能,但是占用更多磁盘空间,在舆情业务上,索引是百亿级别(保留近3个月),基于成本考虑,这里选择了 ik_max_word 分词器。
基于 Elasticsearch 的数据中台
系统架构图
整个数据中台也是分层的架构体系,分为:
- 数据接入层
- 消息总线
- 数据处理与存储层
- 数据索引层(Elasticsearch 集群)
- 智能网关层
- 业务接入层
这里重点介绍数据索引层与智能网关层。
数据索引层
在数据索引层,按照业务特点,以及成本综合考虑。分为近 2年 数据的冷数据集群,以及近 3个月的热数据集群。
- 冷数据集群,选择价格相对低廉的 SAS 盘作为索引的存储介质, 提供离线的数据下载,以及对响应时间不敏感,且时间周期跨度较长的检索、聚合统计等。
- 热数据集群,选择 SSD 盘作为索引的存储介质,每个节点 16C、64G 内存, 为了降低运维成本,以及动态扩缩容,我们选择了 阿里云Elasticsearch 服务。
在索引设计方面,根据业务特点,经常要检索特定平台的数据,对索引按照文章发布平台,以及发布日期做了拆分,使每个索引不至于过大,以及导致每个节点上的数据分布不均匀。提高磁盘的利用率与检索性能。
智能网关层
智能网关层避免了业务端直连 Elasticsearch,无法做到访问并发限制,以细粒度的权限限制。智能网关主要解决了一下几个痛点:
1、并发控制
网关为每个业务分配对应的独立的 TOKEN,并且设置相应的 QPS,防止某个业务的高频访问,影响了其他业务的访问,最终因为级联效应, 导致整个 Elasticsearch 集群无法提供服务。另外, 网关提供了熔断限流的功能,在ES集群负载比较高的况下,对低优先级的 TOKEN 进行限流。
2、权限控制
网关为业务分配对应的权限,比如,读写权限、访问特定索引权限、查询时间跨度权限等,对查询语句进行解析,禁止访问超出权限的数据。
3、SQL 查询
网关提供了 SQL 转换成 DSL 的功能,访问业务端通过标准的 SQL 进行快速的查询对应的数据,提高业务开发效率,降低使用ES的门槛。
4、动态路由
在索引设计阶段,把索引按天、按照发文平台进行了拆分,为了方便业务端查询,根据业务端查询的时间段、发文平台,自动定位到对应的索引,业务端不用关心具体的索引名称,提高业务端的开发效率, 同时,根据查询时间范围,动态查找对应的索引,并在查询时指定到具体的索引,提高查询的速度,避免无效的索引扫描。
5、降低升级成本
由于业务不是直连 ES,后端切换 ES 集群,可做到业务端无感知,降低了 ES 集群的升级切换对业务端的影响, 降低了升级带来的开发成本。
典型业务场景
情绪走势
情绪走势图
通过“情绪走势”图,可以看出一个舆情事件,在一段时间,不同情感表达上的数据分布情况,为了方便使用 ES 的聚合统计功能,对每篇文档的发布时间,设置了news_posthour
(文档发布时间所在的小时)冗余字段,文档的情绪news_mood_pri
字段,通过在 DSL 中嵌套使用 aggregation ,就可以在一次查询中获得对应的图表数据。
比如查询在微博上与疫情相关的博文在某一天每小时的情绪走势,查询语法如下:
GET weibo_2021-04-08/_search
{
"query": {"bool": {"must": [
{"match_phrase": {
"news_title": "疫情"
}}
]}},
"size": 0,
"aggs": {
"NAME": {
"terms": {
"field": "news_mood_pri",
"size": 10
},
"aggs": {
"NAME": {
"terms": {
"field": "news_posthour",
"size": 24
}
}
}
}
}
}
通过上面的嵌套查询 DSL 语句,就可以快速获取到不同情绪分类下,每个小时段的数据量。
热门主题词
热门主题词
通过一个事件的热门主题词,可以直观的了解到一个事件的大概内容。这里也是通过 ES 的聚合功能实时获取主题词的统计数据。为了能够实时获取主题词的统计数据,这里用一个事件中提到每个主题词的文档数量,来当作主题词的数量(相当于默认每个主题词在文档中只出现一次),并没有用每篇文档的主题词的绝对量。这样做有一个好处,可以使用 ES 的 aggregation 功能实时聚合获取统计数据,再配合 TF-IDF 算法,计算每个词的相对权重。
在设置索引 schema 时,定义了news_keywords_list
字段, 用于保存单篇文档的分词结果列表,然后使用如下的语法,就可以快速统计每个词对应的文档数量:
GET weibo_2021-04-08/_search
{
"query": {"bool": {"must": [
{"match_phrase": {
"news_title": "疫情"
}}
]}},
"size": 0,
"aggs": {
"NAME": {
"terms": {
"field": "news_keywords_list",
"size": 10
}
}
}
}
通过上面的 DSL 语句,可以快速统计出高频词以及与其相关的文档数量。
创作人简介:
王欢,近 10 年内容大数据领域从业经验,安徽云计算产业促进会开发者工作委员会发起
人之一,阿里云 MVP。擅长高并发系统设计、数据中台构建等,目前在一家人工智能企
业担任技术 VP,主要关注 AI 算法平台构建、AI 算法在内容分析领域落地等。
博客: https://juejin.cn/user/2981531263175213/posts