Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 我可以选择哪种线程模型?_Multithreading_Redis_Pthreads_Memcached_Threadpool - Fatal编程技术网

Multithreading 我可以选择哪种线程模型?

Multithreading 我可以选择哪种线程模型?,multithreading,redis,pthreads,memcached,threadpool,Multithreading,Redis,Pthreads,Memcached,Threadpool,我正在编写一个类似于键值存储的系统,但不同的是,get和set操作经常被调用 在服务器端,我刚才使用了“每个客户端一个线程”的线程模型。但是在这个应用程序中,每个任务的客户端的连接大约有一万个,所以我使用的模型很慢 在这种情况下,我可以选择哪种线程模型 谢谢您可能应该提供更多详细信息,说明您看到系统如此缓慢的原因。如果您正在使用互斥锁,您是如何设计它们的?互斥锁是否保护整个键值存储或其子集。通常,将大表拆分为单独的小表(行)有助于提高并行性。此外,您是否遇到了一个线程等待另一个线程的问题。如果是

我正在编写一个类似于键值存储的系统,但不同的是,get和set操作经常被调用

在服务器端,我刚才使用了“每个客户端一个线程”的线程模型。但是在这个应用程序中,每个任务的客户端的连接大约有一万个,所以我使用的模型很慢

在这种情况下,我可以选择哪种线程模型


谢谢

您可能应该提供更多详细信息,说明您看到系统如此缓慢的原因。如果您正在使用互斥锁,您是如何设计它们的?互斥锁是否保护整个键值存储或其子集。通常,将大表拆分为单独的小表(行)有助于提高并行性。此外,您是否遇到了一个线程等待另一个线程的问题。如果是这样,您可能会更好地使用条件变量。

实际上,“每个客户端一个线程”模型非常有效。就原始性能、延迟、系统调用次数而言,很难做得更好。但是,它的可扩展性不是很强,因为:

  • 每个线程都有自己的堆栈,因此内存/连接比率很差
  • 操作系统调度开销随着线程数的增加而增加
  • 当在同一资源上阻塞许多线程时,并发管理原语(互斥、条件变量等)的效率较低
我认为选择一个好的线程模型的关键点是评估操作的相对成本,以及它们是否会阻塞。例如,协议编组/解编的成本是否高于对内部数据结构的访问?数据访问能否生成阻塞磁盘I/O?等等

根据结果,您可以想象各种模型

第一种可能的模型(memcached模型):

  • 1个线程(事件循环)用于信号管理和TCP接受管理。 每次接受新连接时,都会将其分派(通过循环)到一个连接管理线程

  • n个线程用于连接管理。 每个线程都是对其关联连接的偶数循环(e)轮询。任何传入的查询都由线程处理。对全球数据结构的任何访问都必须受到某种互斥机制的保护

如果数据结构访问是快速且可预测的操作,则此模型工作良好。如果互斥太复杂,或者全局数据结构上存在太多争用,则可以通过添加专用线程来管理数据结构操作来改进此模型

  • 1个线程(事件循环)用于信号管理和TCP接受管理
  • n个线程(事件循环)用于连接管理
  • 快速内存队列
  • 1个线程处理所有数据结构访问,侦听内存中的快速队列
在此模型中,连接线程对协议进行解码/编码(昂贵的操作),并通过将事件发布到内存队列,将所有数据访问委托给专用线程。一个特定的文件描述符用于在专用线程为连接线程发布结果后唤醒事件循环。所有数据访问操作都是序列化的,不需要互斥来保护关联的数据结构

以前的模型假设数据访问比协议管理本身便宜或更便宜。如果这是错误的,那么以下模型可能更好:

  • 1个线程(事件循环)用于信号管理和TCP接受管理
  • n个线程(事件循环)用于连接管理
  • 快速内存队列
  • m个线程用于数据/查询管理,侦听内存队列
在这个模型中,n个连接线程只处理协议编码/解码操作,并将所有其他任务委托给m个线程池。这些线程必须管理对gobal数据结构的并发访问。最终,如果您有足够的I/O或繁重的计算,它们可能会阻塞


还有许多其他可能的变体,这些只是主要的想法。

您使用的是哪种编程语言?Didier优秀答案的唯一精辟之处是您可以使事件循环线程自伸缩。如果使用epoll()的事件循环线程分析它在epoll()中被阻塞的平均时间,它可以决定它有多忙。如果epoll()总是立即返回,那么线程就跟不上需求。您所需要的只是该线程能够将其一些连接传递回管理线程的方法。然后,这又启动另一个线程来处理这些连接。听起来像是编写了很多代码,但最终会得到一个自调优的服务器应用程序。