shell909090/influx-proxy

请问一下,假如启动2个proxy服务,使用同一份buffer文件,会存在并发问题吗?

Opened this issue · 17 comments

假设我有两个influxdb,分别为influx1、influx2。
还有两个proxy,分别proxy1、proxy2,都连接influx1和influx2,实现相同的功能,从而实现proxy的高可用。

我想到的做法是,将2个proxy的本地持久化的buffer文件通过nfs的形式使用同一份文件。
可问题是,不太知道这样并发写是否存在问题。
并且假如influx1重启,2个proxy也应该会同时根据buffer文件,将数据消费到influx1中吧。
希望您能帮忙看一下这个方案是否可行呢?

并发写有可预见的风险。
其实我不大理解,influx1重启后,proxy1和2会分别把自身的数据写入到influx1中。这个有问题么?

因为之前的计划是proxy1和proxy2使用相同的缓存文件,例如local.dat。
当influx1重启后,proxy1以只读的方式打开local.dat,将数据消费到influx1.
与此同时,proxy2也进行相同的操作。那就相当于重复的进行了写入操作。

重复写入并无必要,而且你还要面对local.dat的跨节点竞争写问题。

刚才根据您的意见已经将这个方案否定掉了。
现在打算实现proxy高可用的话,已经打算启动2个相同功能proxy,在上层加上一个nginx实现负载均衡。

proxy高可用方案的正解是heartbeat或keepalive。上层再加nginx,如果只有一个,nginx本身不HA。如果有两个,等于没用。
加nginx的话,需要加到目标设备上。如果目标设备离线,那原始监控数据也不用提HA的事了。

哦,我们打算使用k8s部署方式来保证服务的高可用

那你也可以用k8s方式直接保证proxy的高可用。

假设角色有influx-porxy、influxdb1、influxdb2. influxdb1存在缓存,influxdb2正常提供服务。
1、influxdb1缓存文件写如不是实时进行的,而是大于MaxRowLimit,或者一秒(配置的设定值)内进行文件的读写。
当一秒内proxy服务停掉,那是否此部分(在内存中未写入文件)的数据会丢失?可以将 定时刷新的值设置得特别小呢?或者MaxRowLimit设置为1,实时写文件?。
2、当influxdb1数据从缓存文件中进行恢复时,同时进行数据的发送。这个过程不能保证到达influxdb的顺序是数据发送请求的顺序,
例如:influxdb1缓存文件中存在series=series value=1的数据。当influxdb功能恢复时,influxdb1接收请求series=series value=2的数据。
value=1 在value=2之后执行,就会存在最终不一致的情况了。
influxdb1中value=1,而influxdb2中value=2?不知道我思考的是否正确,希望作者能给予一些建议?

这些个问题我没测试过,只凭我对系统的了解猜测一下:

  1. 写出是缓存在应用内,而不是系统缓存。所以如果发生服务重启,数据会毫无疑问的丢失。如果将刷写间隔变短,会出现频繁写出,增加IO压力。如果MaxRowLimit设定为1,iops基本等同于数据条数。qps大于1000的时候很可能会把进程写死。
  2. 从实践上说,同一个数据就不应当存在覆盖的问题。influx proxy不能严格的保证次序,无论是online写入还是crush recover。因为influx至少需要两个node,而两个node转发速度是不对等的。假设value=1被写入proxy1,value=2被写入proxy2。两者到达backend的先后次序无法保障。即便在同一个proxy,也有非常小的概率出现翻转。只有在写入channel之后,顺序才能被严格的限定。
nmonz commented

@shell909090 您好 我想问下在config.py配置文件中的nodes、defdefault_node的作用是什么以及其中zone代表是什么,指的是influxdb的库吗?测试跟我的理解有偏差。

机房地域。proxy策略是,多个机房同时写入,优先查询本机房。

nmonz commented

@shell909090 那意思是查询和写入没走nodes,我测试时,就算nodes和default_node为空,查询和写入也没问题。nodes只是做了一个地域机房的标记吗?

那你有没有查询写入的时候把本机房的backend关掉试试呢?

nmonz commented

@shell909090 backend关掉就不能写入和查询数据了,只能NODES和defalut_node为空,还不能注释。

  1. 你需要两个backends.
  2. 这两个backends处于不同的zone.
  3. 某个measurement同时映射到两个backends.
  4. nodes的zone和其中的一个相同.

在满足以上条件的情况下,你的所有写入都会发送到两个backends,你的query会被发送到同zone的backend。

在关闭同zone的backend时,query会被发送到跨zone的backend。

nmonz commented

@shell909090 这个已经测试过了 我才用了三个backend,而且都是处于不同zone中。我现在比较麻烦的是node中就算不配置zone和db也可以访问到backend中去。这块不太理解这个NODES在这是怎么样的存在。按照我的理解NODES就是一个查询的入口,通过NODES将查询映射到对应的backed中去?如果是这样为什么我在清空NODES还是可以正确映射到对应的backend上去。

因为所有nodes用的是同一个映射关系。nodes数据结构里主要是描述这个node的属性,例如zone。zone主要影响query的优先顺序。如果没有zone,那么query的时候是随机的。