【教程】Hbase+ElasticSearch构建海量数据检索平台

导读

当前文章构建在读者已经了解Hbase与ElasticSearch相关技术的前提下,如果读者对这两个数据库较为陌生,那么推荐以下两篇文章:
《可能是最易懂的Hbase架构原理解析》
《原来 Elasticsearch 还可以这么理解》

看到这个标题,了解ElasticSearch的同学可能就要说为什么做数据检索要加上Hbase,ElasticSearch本身的存储性能不是就足以支撑海量数据吗?
首先ElasticSearch针对海量数据的存储我认为存在两个较大的缺点:
1、写入效率相对较低,虽然和Hbase一样都是采用LSM树(LSM 通过将磁盘的随机写转化为顺序写来提高写性能 ,而付出的代价就是牺牲部分读性能。),但是ES在写入时需要消耗大量的时间去进行分词、主副本构建倒排索引等操作。
2、(深有体会) 在大数据领域,我们在使用数据的时候,经常用到的字段也就那么几个,剩下的字段要么没有价值要么使用频率极低。
例如安全日志数据中的攻击手段与攻击内容描述字段、用户行为日志中的行为描述与访问操作字段、系统运维日志的进程操作与网络请求内容等字段。
以上无用或低频字段会占用大量的索引空间,由于ES的倒排索引存储在文件中,为提高访问速度,在启动时都会把它加载到内存中。上述问题会导致倒排索引文件过大,从而导致集群性能下降并降低数据访问速度,且会增加不必要的内存硬件成本。

架构设计

为了解决上述中出现的问题,我们需要引入Hbase对上述出现的问题进行弥补。
1、写入效率问题:Hbase基于HDFS存储,其次因为没有索引,不需要考虑海量数据下因为索引导致的性能瓶颈,所以Hbase非常适合存储海量数据,写入速度快,可扩展性强。
2、字段过多导致的性能问题:我们可以将原始数据存储至Hbase中,仅将需要进行检索的字段抽取出来存储至ES中,这样可以大大降低ES因为倒排索引文件过大导致的性能压力。
其次Hbase支持根据rowkey进行模糊查询,rowkey我们可以把它看做成Hbase中单条数据的唯一ID,同时也可以作为一个简单的索引。rowkey的设计是一门学问,可以参考这篇文章:《用大白话彻底搞懂 HBase RowKey 详细设计》
有了上述知识之后,有经验的读者可能就知道如何将Hbase+ElasticSearch结合起来了:根据rowkey将Hbase的原始数据和ES中的检索数据关联起来。
在原始数据(你也可以叫源数据、贴源层数据、日志数据)入库时,我们可以根据数据生成rowkey(rowkey的设计因人而异,最好根据具体的业务来设计,注意要确保唯一性),之后将需要检索的字段抽取出来形成单独的一条索引数据,并将刚才设计好的rowkey放进去,之后将原始数据根据rowkey写入至Hbase,检索数据根据rowkey写入至ES中。
我们在进行检索时首先根据检索条件去ES中搜索,搜索出相对应的检索数据后,根据检索数据中的rowkey直接去Hbase中获取原始数据即可。
架构图

性能测试

有读者可能要问了,原来只使用ElasticSearch的时候,数据只需要写入一遍,也只需要查询一次ES就可返回想要的数据。现在使用了Hbase+ElasticSearch后,不仅数据需要写入两份,查询也需要先查ES,然后再根据ES的查询结果去Hbase中取数据。这样多此一举性能难道真的能提升吗?
在这里插入图片描述
但是经过我多次测试后,单ES架构和Hbase+ES架构的性能对比可由上图直观的展示出来:
在数据量小的时候,单ES架构的性能是优于Hbase+ES架构的。
数据量过了一定量级的时候,Hbase+ES架构的性能就远远的把单ES架构给甩开了。

实战举例

数据写入

{
    
    
    "machine": {
    
    
        "country": "",
        "city": "",
        "description": "",
        "type": 2,
        "operatingSystem": "Microsoft Windows Server 2008 R2 Enterprise Edition 64-bit",
        "mac": "00-50-56-8D-E5-C8",
        "installSource": 1,
        "userIdentityCode": "",
        "newMachineId": "7088160ee3dc39bc03b78f72397b35",
        "osVersion": 102,
        "province": "",
        "osType": 0,
        "id": 1068,
        "thirdpartid": "",
        "packageNum": "",
        "updateDatetime": "2020-09-08 23:52:54",
        "level": 1,
        "ip": "192.168.1.11",
        "packageId": 1,
        "groupname": "",
        "tempIp": "192.168.0.1",
        "createDatetime": "2020-03-23 15:12:19",
        "checkedflag": false,
        "machineId": "0",
        "name": "",
        "time": "",
        "softwareVersion": "win_3.1.18.10"
    },
    "eventLog": {
    
    
        "logType": 1,
        "standardTimestamp": 1588272682000,
        "insScore": 0,
        "operationExtra": "",
        "dealSuggestion": "该类事件的报警,说明网站服务器正在被上传可执行文件。开启强制访问控制,并通过事件管理分析事件详情及日志,查找被上传可疑文件的漏洞,对其进行修补。",
        "subject": {
    
    
            "process": "C:\\Windos\\Softwretion\\Download\\Install\\NDP48-x86-x64-ENU.exe",
            "file": "",
            "filehash": "",
            "type": "",
            "user": "",
            "webPagePhysicalPath": ""
        },
        "typeName": "应用上传二进制文件",
        "description": "应用存在漏洞被利用上传了二进制文件",
        "ucrc": 3755904924,
        "machineName": "",
        "standardDate": "2020-05-01",
        "result": 0,
        "score": 0,
        "insLevel": 4,
        "newMachineId": "7088ae9bc03b78f72397b35",
        "action": {
    
    
            "alarmText": "您的服务器 (192.168.1.11) 有可疑进程创建二进制文件,请及时处理。详情请登录云中心查看。",
            "alarmHtml": "您的服务器 <span class='innerIp'>(192.168.1.11)</span> 有可疑进程创建二进制文件,请及时处理。详情请登录云中心查看。",
            "html": "可疑进程 <span class='process'>C:\\Windows\\Softwibution\\Download\\Install\\NDP48-x86-x64-ENU.exe</span> 创建 二进制文件 <span class='file'>d:\\7c471f50a46c41ade1570cb55c\\1033\\setupresources.dll</span>",
            "text": "可疑进程 C:\\Windows\\SoftwareDistribution\\Download\\Install\\NDP48-x86-x64-ENU.exe 创建二进制文件 d:\\7c471f50a46c41ad0cb55c\\1033\\setupresources.dll"
        },
        "localTimestamp": 1588273219000,
        "id": "aTCBWUJFsoa9asfGWe9Xy",
        "localDate": "2020-05-01",
        "phase": 3,
        "summary": "",
        "alarmEventId": "432e2bed52967b4ebd0c_2020-05-01",
        "eventId": 50001,
        "backId": "3755904_2020-05-01",
        "userIdList": [
            16181
        ],
        "srcip": "10.51.58.18",
        "destip": "192.168.0.1",
        "treepath": "",
        "srcEventId": "00050001",
        "srcIpAddress": {
    
    
            "area": "朝阳区",
            "country": "中国",
            "city": "北京",
            "county": "",
            "region": "",
            "type": "直辖市"
        },
        "groupName": "可疑二进制文件",
        "eventLogList": [],
        "phaseDesc": "控制",
        "innerIp": "192.168.1.11",
        "operation": "create",
        "desc": "",
        "object": {
    
    
            "other": "",
            "proc": "",
            "regkey": "",
            "dst": "",
            "src": "",
            "ip": "",
            "command": "",
            "url": "",
            "webLeakageList": [],
            "file": "d:\\7c471f50a46cde570cb55c\\1033\\setupresources.dll",
            "webLoopholeList": [],
            "regvalue": "",
            "domain": "",
            "host": "",
            "portList": [],
            "filehash": "abfe75ce71cc472461820b0ff1b5badc6451"
        }
    },
    "id": "aTCBWUJFsoa9asfGWe9Xy"
}

以上是一条具体的网络安全日志(已做脱敏处理),当前日志日增量数亿条,存量近百亿条。我们可以看到数据中字段较多,且存在较多的描述性字段。

"alarmText": "您的服务器 (192.168.1.11) 有可疑进程创建二进制文件,请及时处理。详情请登录云中心查看。",
"alarmHtml": "您的服务器 <span class='innerIp'>(192.168.1.11)</span> 有可疑进程创建二进制文件,请及时处理。详情请登录云中心查看。",
"html": "可疑进程 <span class='process'>C:\\Windows\\Softwibution\\Download\\Install\\NDP48-x86-x64-ENU.exe</span> 创建 二进制文件 <span class='file'>d:\\7c471f50a46c41ade1570cb55c\\1033\\setupresources.dll</span>",
"text": "可疑进程 C:\\Windows\\SoftwareDistribution\\Download\\Install\\NDP48-x86-x64-ENU.exe 创建二进制文件 d:\\7c471f50a46c41ad0cb55c\\1033\\setupresources.dll"

根据之前提到的架构建设要求,我们首先需要根据原始数据生成一个rowkey,这里为了方便演示我们直接将原始数据的id字段作为rowkey。然后将原始数据根据当前rowkey写入至Hbase中。
其次我们需要抽取出常用的字段构成检索数据,在网络安全领域,我们最常用到的字段无非以下几个:

数据id
攻击源ip
攻击目的ip
攻击类型
攻击描述
攻击时间

于是我们就可以将以上字段在原始数据中找到并抽取出来,组成检索数据

id:aTCBWUJFsoa9asfGWe9Xy
src_ip: 10.51.58.18
dest_ip: 192.168.0.1
attack_type:应用上传二进制文件
attack_description:应用存在漏洞被利用上传了二进制文件
attck_time:2020-05-01 02:51:22

抽取完成之后,我们根据检索数据中的id将数据写入至ES中。这样我们的数据写入工作即可完成。

数据检索

数据写入完成后,我们输入检索条件:192.168.0.1 ,将当前检索条件输入至ES中,可以得到以下数据

id:aTCBWUJFsoa9asfGWe9Xy
src_ip: 10.51.58.18
dest_ip: 192.168.0.1
attack_type:应用上传二进制文件
attack_description:应用存在漏洞被利用上传了二进制文件
attck_time:2020-05-01 02:51:22

检索到当前数据后,我们再根据数据中的id,将此id的值作为rowkey去Hbase进行查询,即可获得原始数据。

优化意见

1、根据Hbase中rowkey可以模糊搜索的特性,我们不仅可以做到检索数据和原始数据的一对一关系,在某些特定的场景下,甚至可以做到一对多,多对多的关系。
2、Hbase和ElasticSearch集群不建议放在同一批机器上。因为ElasticSearch需要消耗大量的内存,Hbase占用大量的存储,为了更好的分配存储和计算资源,所以建议分开放。
3、因为Hbase默认不支持聚合操作,需要引入coprocessor特性实现,且效率较低。ElasticSearch原生自带聚合操作,且性能很好,所以我们也可以将一些需要进行聚合操作的字段也存入ElasticSearch中。

心得

网上有很多Hbase集成ElasitcSearch的文章,有些文章只是简单的介绍了一些优点、架构、搭建等内容,有的文章就写的很详细,包括业务上的一些背景和需求,甚至源代码都加上了,那为什么我还要写这篇文章呢,主要有以下几点
第一:别人的文章终究是别人的经验,只有自己了解学习后并且按照自己的实际情况实现才是自己的,才算是真正的融会贯通。
第二:每个技术人都有分享的冲动,自己实现了之后就想着把自己遇到的一些经验和好的点子分享出来,毕竟这篇文章也是通过别人分享的相关内容,自己学习透彻后才可以完成。
第三:写文章的过程也是对当前项目总结和反思的过程,哪怕过了很久有些关键点忘掉了,回过头来看之前写的文章也能很快的拾起来。

猜你喜欢

转载自blog.csdn.net/mrliqifeng/article/details/111771109