本文主要是介绍曾经参与的数据实时提醒的一种设计回顾,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景描述:这一篇说到指挥平台基本都是统计,大部分统计都是前一天的数据,也有一些统计是要求实.时的,今日动态就是实时统计中的一种:显示一些业务新增的记录数和记录信息
设计分为两部分,一部分是提供数据,一部分是查询数据
提供数据:通过Schedule线程池定时调度各业务查询实现,查询新增的数据,然后插入实时数据中间表
查询数据:维持一个SseEmitter连接
由一个线程通过EventStream实时向前端推送
SseEmitter发送数据
1.提供数据大概的实现过程
大概过程是各业务实现事件抽取接口,查询新增的数据,由一个抽取器调用,向Redis写数据,然后再从Redis里面拿数据向实时数据表写入
1.1 业务事件抽取器
抽取指定范围内的业务事件
1.2 事件Poll器
Scheduled线程池定时抽取
初始化Bean后,afterPropertiesSet
获取所有实现的抽取器
然后分桶,通过线程池定时调度。map的key是桶号,value是对应的抽取器集合
对于每一个抽取器,通过线程池调度
ExtractJob实现Runnable方法
run方法
下面就执行抽取
1.3 从redis将动态消息抽取到实时数据表
也是维护了一个Scheduled线程池
afterPropertiesSet设置这个线程池
从Redis读取
2.查询数据大概的实现过程
大概过程是这样
2.1 维护客户端队列和数据提供器无界队列
2.2 数据提供器supplier查询数据
2.3 向客户端推送
SseEmitter.event的数据由SseEmitterHolder提供,在初始化客户端时调用init方法,调用supplier的方法
思考和讨论:
1.这里用到了Scheduled线程池线程池,什么时候可以用Scheduled线程池?
在需要定时调度的场景下可以考虑Scheduled线程池,并且是要可以自己接管的。咱们说的分布式调度框架一般不能自己接管调用过程、结果等。这是我的思考。
2.为什么提供数据和查询数据要分开
这个我觉得要实现数据实时展示其实是一个复杂的过程,首先要确定数据来源再是数据如何展示,将提供数据和查询数据分开也是一种解耦,出问题时可以从两个方面去排查,如果在一个过程连续完成,局面有点太大了,就有点面向结构化(过程)的设计了,不太符合面向对象的设计。
3.为什么数据要先放到Redis
我觉得主要是因为要展示的数据格式和查询出的数据要做转换,Redis作为缓存或内存数据库,在这里起到内存数据库的作用,是一个中间层,起到承上启下的作用。
4.hash code不和保证唯一性
这里是通过Hashing.murmur3_128实现,不是很了解
这里的目的是为了比较事件间的hash值来增量添加而不是全量添加,这一块没有深入debug过,感觉是那么回事但不是很确定。通过事件的hash和redis记录的hash比较判断当前事件是否需要更新
这个过程挺复杂的,如果要自己设计,照葫芦画瓢或许可以,但核心是设计思路和为什么要这么设计,现在是别人实现了去看,自己设计并实现的过程中肯定会遇到很多问题,这也是必须要经历的过程。
以上思考都是个人观点,也主要是给自己看看,有疑问的朋友欢迎一起讨论。
这篇关于曾经参与的数据实时提醒的一种设计回顾的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!