记一次性能优化问题

记一次性能优化问题

参与架构

代码设计

我们总假设,温度是一次次上报的,且点与点之间没有先后的顺序

很容易写出以下代码

For(EachTimeUploadData)

Pipe.collect(in,out,now)

遇到的问题

我们的不仅需要记录温度,还要记录压力和流量,而这些属性是归属于管道

这个时候会遇到一个巨大的问题,数据库的DeadLock

我们默认聚合根是Pipe,那么为了防止聚合根在两个线程中出现,故而数据库中是要对这一行开启事务的,意味着根所在一行是要锁行的,而测试中如果遇上同一根管道的首尾同时上报数据,那么就会发生DeadLock,更不要提某些情况下是要沿着管道将沿途所有的管道锁定的问题。

解决死锁

  1. 我们不能允许数据丢失
  2. 不能够对架构做大改动

要解决死锁的问题,最简单的办法时,我们只用一个线程来操作,在不考虑集群的情况下,将原有方案变更为,数据上报时候顺序写入文件,然后开启一个线程从文件头开始反序列化数据然后逐一写入数据库。

集群环境

在集群环境下,依旧有锁冲突的问题,那么冲突时候策略就可以考虑以下了,我选择了,冲突之后将数据放入队列尾部,这个时候代码逻辑上是没什么问题了

性能

可是上线之后发现,其写入性能仅在15s,注意是s,是秒,才完成50条入队消息的消费

在各种断点之后,依旧发现瓶颈在数据库与应用中

  1. 每次查询流量系统地址,30~50ms
  2. 每次查询流量,30~50ms
  3. 每次查询管道链条300~500ms

在一些支管上,单次插入可以达到最大5000ms

解决

  1. 增加管道标记父节点字段,而非靠查找所有管道再通过计算得出父节点
  2. 增加本地缓存和Redis缓存切换,以其在没有redis环境下可以降低查询流量系统地址的时延
  3. 优化流量和压力的Opc客户端,减少数据传输量
  4. 将于数据库交互中的插入和更新变为Batch形式

测试结果

消费50条数据仅需要300ms左右,

网络路径是如何被发现的

网络路径是如何被发现的

最近突然好奇到,我们熟悉的IP网络是如何运作的,查了半天资料都是说TCP/IP那几层协议,根本没有说网络是如何运行的。那我们试试头脑风暴,再发明一次网络吧

一个理想的模型

网络是由无数个可以相互连接的点组成

一些限制

每个点是没有先验知识的,也就是说,点与点之间如果不是直接连接在一开始是不知道能否由通路的,但点能知道直接连通的道路

发现通信路径

在没有点与点之间没有先验知识的前提下,我们就只能通过BFS/DFS算法来发现路径
所以当第一次通信的时候,点与点之间的时间最优情况T(n^n) (假设每个点直接连接n个点,在第二跳就能找到通路)

问题

这个情况下,我们会发现性能是和我们现在的网络不同,应该是会很慢的

优化

如果需要提升性能,就需要增加先验知识

增加假设

点的直接通路中由特定的点具有网络通路的解释权,我们称之为高优先级点,高优先级点的位置应该预先内置在访问点处,高优先级点数量m << n

优化结果

性能会提升至T(m^m)

再增加假设

假设我们可以广播,亦即是发出一个信号,如果点能到达,则返回路径表,此时的实际访问次数是T(h) h是网络中的最先达成通路的深度

问题

在未达成通路之前,整个网络相当于开启了m^m^h个半连接,会产生信息风暴

优化

划分网络,减少同时建立的半连接数量

对应到我们真实的IP网络

这个时候是不是就有点像我们的现有的IP网络了

硬件层就是能直接连接的路径

需要中间转发的,就在IP协议层完成

比如ICMP就是我们的广播信号

在一些核心交换机上还存在手工配置的路由表,就是高优先级点的先验信息

网关就是我们的高优先级点

划分就是我们的掩码

当然这都是我瞎几把想的东西,和实际出入应该大了去了,IP网发展了这么多年,基本模型都有可能变了