请教一个并发设计问题

2023-05-08 07:37:55 +08:00
 swqslwl
我在做一个监测流量的项目。每秒会从数据源中获取 1w 条 json 格式的流量信息,我希望对这些流量进行分析,但是现在会出现丢数据的情况。

我的做法是
1.接受到数据后先传入 channelA
2.启动一个协程循环从 A 中读取数据存入切片 B
3.另起一个协程处理切片 B 的数据,同时在处理业务时利用 mutex 锁住 B

实际调试中发现,mutex 的次数会影响数据的丢失量
请问我这样设计是否有问题,是否会导致丢数据
4020 次点击
所在节点    Go 编程语言
39 条回复
RH
2023-05-08 07:58:19 +08:00
需要 demo 才能分析,你描述的逻辑里有很多不确定性。
lrh3321
2023-05-08 08:18:57 +08:00
要 demo, 你两个协程都会写切片 B
ox180
2023-05-08 08:44:29 +08:00
@lrh3321 冒泡
piaodazhu
2023-05-08 08:54:24 +08:00
我就提一个可能,切片 B 扩容,导致这种特殊情况:
时刻 1 ,goroutine1 加锁,用 B=append(B, item)向切片 B 追加一个元素。刚好触发了扩容,B 的底层数组指针发生了转移。即,append 的参数 B 和返回值 B 中的 ptr 不同。
时刻 2 紧接着时刻 1 ,goroutine2 拿到锁,这个时候在 goroutine2 看来,B 只是一个由(size,cap,ptr)构成结构体,它察觉不到 B 底层数组指针的变化,所以看不到 goroutine1 追加的数据。

具体可以检查一下代码。
xuboying
2023-05-08 09:04:24 +08:00
我感觉 sync.Pool 是干这个事情的。但是我一直没有掌握 sync.Pool 的正确用法,希望有大佬解释一下。
ding2dong
2023-05-08 09:04:28 +08:00
调大 A 的 bufsize
ding2dong
2023-05-08 09:05:47 +08:00
另外写入 B 的时候也要 mutex ,否则会被污染
lysS
2023-05-08 09:07:39 +08:00
“但是现在会出现丢数据的情况” 这是为什么呢?实际没有从数据源中获取到 1w 条?
liangkang1436
2023-05-08 09:08:47 +08:00
有没有考虑用时序数据库来存储这些数据然后订阅? 1w/s ,这个数据量不小了
fregie
2023-05-08 09:21:16 +08:00
2 中存入 b 的过程也要锁。
其实这里不用切片用队列比较合适
ghost024
2023-05-08 09:21:48 +08:00
没看到你的代码,粗略的分析,你的第一个协程,从 channelA 中写到切片 b 也需要先获得 b 的 mutex 锁的,要不然,如果在锁 b 的时候你从 channelA 中获取数据,因为 b 锁住了,你写不进去就丢了
WispZhan
2023-05-08 09:28:28 +08:00
The Golden Rule - Don't Block the Event Loop or Coroutine.
Martens
2023-05-08 09:32:34 +08:00
写切片 B 和读切片 B 的时候都要加锁
dode
2023-05-08 09:40:47 +08:00
先放 kafka ,再批量读出来处理呢
8355
2023-05-08 09:42:27 +08:00
@ghost024 #11 +1 跟我理解的一样
而且整个过程感觉效率并不高
使用中间件哪怕 redis stream 整个代码都可以简单很多
joesonw
2023-05-08 09:52:00 +08:00
能确定数量就用 channel ,不行的话用 linked list 。尽量避免用锁,传递锁的时候要传指针&。
matrix1010
2023-05-08 10:09:41 +08:00
丢数据算 bug 吗? 如果算请写个并发的单元测试并加上-race 测一下
Nazz
2023-05-08 10:19:36 +08:00
数据量有点大, 建议使用 sync.Pool + 任务队列
swqslwl
2023-05-08 11:21:56 +08:00
@lrh3321
@RH 老哥代码放上了
swqslwl
2023-05-08 11:22:55 +08:00
@ding2dong
@fregie

@ghost024
@Martens
@8355 对,这里确实是有问题。但是我加上后发现还是会丢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/938125

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX