背景
最近一直在折腾告警查询优化的问题,我们场景:用户希望查询其所负责设备的最近10条告警消息。我们系统存在两端访问:一个是PC端,另一个是小程序端。其中,PC端并发少些,小程序端并发要求比较高,需要达到500+TPS。由于设备量比较多,我们预估一个月的告警数据量在1000万+。另外,用户可以对告警数据进行处理操作。如何在兼顾大数据量的秒级查询及高并发的范围查询,我们做了一些探索和尝试。
ClickHouse
PC端我们是通过ClickHouse的ReplacingMergeTree引擎来实现告警查询及处理的。具体的实现过程,可参考我的这篇文章:基于ReplacingMergeTree来实现告警处理。由于ClickHouse的并发性能不行,在我们8C 16G虚拟机上,1000万数据ClickHouse的查询并发在10以下,与500相差甚远。优缺点整理如下:
优点:
1、以新增替代更新(告警处理),性能高,吞吐量大。
2、查询性能高,千万告警数据,分页查询平均响应秒级。
缺点:并发查询能力不足。
针对ClickHouse并发问题,我们也做了相关的优化:一方面,考虑到告警处理的业务场景并发不高,操作不频繁。告警处理的时候,可以一并触发表Merge过程,通过OPTIMIZE TABLE yourtablename FINAL。这样告警查询的时候少了聚合操作,性能有3倍左右的提升。另一方面:还是要提升SQL执行的整体性能,经过第一阶段的优化,在8C 16G的VM上,300万左右的告警数据,单次查询响应时长在:300-500毫秒左右,TPS在10左右。我们可以适当的增加CPU或者换个好点的磁盘,或者干脆直接换物理机器,来提升查询的总体TPS,目测100+还是很容易达到的。
在有限的资源下,如何提升查询并发数?我们是ClickHouse的重度使用者,既然ClickHouse做不到,那么哪个中间件可以呢?分析下我们的业务场景有两个特性是ClickHouse不擅长做的:更新和高并发。我们想到了Redis。
Redis
zset 是 Redis 提供的最具特色的数据类型之一,首先它是一个 set,这保证了内部 value 值的唯一性,其次它给每个 value 添加了一个 score(分值)属性,通过对分值的排序实现了有序化。我们想通过ZSET来实现高并发查询,遇到了如下难题:
1、小程序端查询的筛选条件很多可以自由组合
2、用户能看到其所属组织下所有设备的告警信息
一条告警上报的时候,我们会在告警接收模块进行告警的维度信息补齐,比如:告警设备所属组织树path。ClickHouse中是通过在告警表里面增加组织树path字段,查询的时候通过组织树的path进行模糊匹配来实现的。那么在Redis,我们打算以告警设备所属的组织树path为key,分数为告警时间,value为告警的内容。形如如下的操作:
zadd 00-AH-a7tyhJqS-sXSln4GS 1648733430000 "{...}"
对于组织树模块like的场景,我们可以通过zunionzstore命令求多个set的并集来实现。形如:
zunionzstore set1 set2 set2... uset
然后通过ZSCAN 命令进行筛选,这块其实类似于hbase的rowkey原来,我们需要好好的设计redis中的value的构成。需要将筛选条件一并设计进去。比如:read=0&type=1#{...}。那么我们可以通过如下脚本过滤出read=1的数据。
scan uset 0 match "read=1*"
此方案在数据量比较小的场景下应该是没问题的,如果set数量比较多,而且每个set数据量比较大的话,性能应该是无法保证的。比如:每个set里面有百万数据。
MySQL
我们再回到MySQL上来。更新的场景OLTP数据库都快不起来,只能采用预编译批处理的方式:一批1000,慢慢来更新。我们惊喜的发现:对于我们的查询场景,MySQL非常适合。因为MySQL索引的底层数据结构就是B+树。我们只需要在告警表中,增加告警时间的索引。由于本身索引构建的时候就是顺序构建的,我们的查询场景order by字段只有告警时间,所以整个查询过程非常的快。查询1000万条告警信息,按照告警时间倒序排序取前10条,响应时长在毫秒级。使用mysqlslap对查询SQL进行压测,发现在我们如此脆弱的虚拟机上(8C 16G)上,告警查询TPS也能达到500+,完全能满足我们的业务需求。
尾记
至此我们也能总结出比较合适的方案:更新、简单的高并发范围查采用MySQL数据库,OLAP场景大量数据的秒查采用ClickHouse数据库。MySQL中数据通过binlog的方式同步到ClickHouse数据库中。这件事情给我的感触还是比较深的:这个世界永远没有银弹,合适的才是最好的。有时候一直存在的东西,也许都是各方权衡的结果,永远没有最优的解,唯有一直的努力!

网友评论