基于MQ实现实时监控系统(一)

最近项目开发一个实时监控的系统。该项目的实现主要是基于mq,实时消费对应的最新数据,对一些指标进行监控。对应的监控规则下,如果产生对应告警,就会发送通知给用户,同时实现一些基本信息的管理以及统计等功能。

关于使用的消息中间件

本系统采用的是基于rockemq封装的消息中间件。具体的相关知识不展开介绍。项目中遇到一个问题是消息堆积量过大的时候,消费速度会变缓慢。
解决该问题的尝试:
1,先从自身消费速度上找原因,但我的情况是直接空消费(不做任何数据处理)也很缓慢。具体的原因应该是mq自身做了限制,未深究。
2,因为跟mq做的是长连接,也就是不断的拉取数据,可以设置增大一次拉取的数量。但本地的缓存数量好像也有限制。还是没有解决我的问题。
3,最后查看mq的客户端,可以看到我消费的那个topic消息是很不均匀的,也就是所有的消息都只往一个brocker中发送。导致无法提高并发能力。
通过修改生产者的配置,将问题解决。
PS:不能在钥匙孔里找钥匙。

关于多线程消费并发带来的线程安全问题

为了提高消费能力,同时mq是支持多线程消费数据的。所以该系统还会遇到多线程消费带来的并发问题。
主要在于该监控系统会有一个重复次数的问题。也就是说当某种状态重复次数达到预定值得时候才产生告警。这是的重复次数对多线程而言就会存在不安全的问题。
最简单粗暴的方式就是直接在可能存在线程安全问题的代码段加上一个锁。将并发问题线性化,这个就是解决线程安全的本质。
除此之外还有可能在插入数据库的时候出现并发问题;
也就是说当两个线程同时出现告警,此时去查询数据库都没有这条记录存在。就可能出现重复插入的情况。
为了解决这个问题:
1,最粗暴的方式也是直接在代码块中加一个锁,但这解决不了分布式并发问题(后面再做说明)。
2,第二种做法是通过数据库层面去控制。采用insert into …select的语句,用数据库来保证线性操作。

分布式带来的问题

为了提高系统的处理消息能力,同时也为了保证系统高可用性,该系统部署了多个实例。也就意味着之前一些本地缓存的操作都因为分布式而需要改造,为此引入了redis来解决分布式缓存问题。
1,本地缓存刷新问题;
在我们的系统中总存在一些数据是比较频繁使用但是又不经常改变的。为此我们的第一反应就是将其取出直接放置到本地缓存,提高系统性能。但是分布式中存在一个问题就是当我更新缓存时,如何做到所有的实例的缓存都被更新的问题。
毫无疑问我们一定是触发更新操作,修改数据库后通知所有的节点都去更新。那么如何做到各个节点的通信就是关键了。笔者采用的是Redis的发布订阅功能,用redis建立一个topic,所有的节点都订阅,做到及时更新。(具体不做详解,网上也有许多解决方案)
2,定时器只需要执行一次的问题
分布式系统中要如何保证定时任务只能被执行一次,那就是要通过分布式锁来实现。简单来说也就是利用Redis 对一个值进行设置,在程序中实现,利用Redis过期的函数,只有该值过期了才能重新获取锁。

数据库索引

1,建立唯一索引
许多重复数据的校验,之前的做法都是需要先查一遍数据库,然后遍历是否有重复值得出现。而现在采用的是利用数据库自身提供的实体完成性,根据业务的需要建立一些唯一索引进行校验。
2,建立索引,提高查询效率

    系统目前处于优化阶段,还有很多问题未解决,暂时写这个遇到的问题。未完待续。。。。如有大佬看到此文章,欢迎指点一二,请不吝赐教。一枚小菜鸟程序媛的进阶之路。

你可能感兴趣的:(基于MQ实现实时监控系统(一))