关于graphd和storage的线程模型

我们发现当查询大量数据时, (比如一个请求返回200万数据), 会使写入性能大大降低, 虽然我们部署了3台机器, 3个graphd, 读取时控制了最多8个并发, 写入128, 但是写入时仍然会被卡住很久, 这时候如果把读取并发关掉, 写入性能马上就提上来了

请问, graphd 执行的线程模型是什么样的? 一个graphd 核心最多能支持多少并发工作? 和storage 通讯是单线程还是多线程? storage 的读写最多支持多少并发? 当写入时, 有锁吗? 这个锁的粒度与什么有关?

另外, 按照官方的推荐配置, 我们是否可以通过在一台机器上部署多个graphd(比如部署3个graphd) 来提高吞吐量?

谢谢!

1 个赞

你看过dstat IO CPU 和NETWORK吗?graphd 和storaged CPU分别是多少
— 你确定是定位到 bound 在 graphd的CPU上?

你要多加几个graphd是可以的,这也是分离设计的初衷

如果你觉得是graphd 的问题的话,可以多启动几个graphd进程。 graphd是无状态的,相互之间也没有通信(记得检查下它的配置文件,连接到正确的meta和storage就行)。
然后,不同类型的应用向不同的GraphD进程发请求。 也可以这样对比看看。

graphd 的线程模型可以理解成一个大的线程池,所有 query 的任务都是丢入这个线程池,通过异步的方式来执行并返回结果。

graphd 最大能支持的并发数取决于你为其配置的最大线程数,即上述线程池的大小,如果不设置(默认0)则使用 cpu 核心数。

graphd 和 storaged 的通信是通过 thrift 的 RPC 来实现,是使用的单线程还是多线程取决于当前 query touch 到的 partition 数量,如果是涉及到多个 partition,那么 graphd 在向 storaged 请求数据时,会同时向对应 partition 的 leader 发送请求,并汇总结果给前端。

storaged 的并发度也是可以通过 gflags 配置的,但是一般不建议直接修改该值。现在每个 partition 的数据只能通过 leader 读取和写入,所以在 storaged 这边没有加锁,而是通过排队的方式来处理所有的请求。

上面你的一个 query 的返回结果很大,怀疑是当前的查询阻塞了后面的写入的请求,因为query请求时间较长,多个相同 query 同时请求就将 storaged 的 worker 线程耗尽,阻塞了后面的所有请求。

现在 storaged 还没有完成资源隔离的实现,后面会提供更好的优化策略,感谢您的反馈。

1 个赞

谢谢