2

我遇到了一个特定的问题并想到了解决方案。但是由于该解决方案涉及很多,我想知道其他人是否遇到过类似的事情并可以评论最佳实践或提出替代方案。

问题如下:我有一个用 Django 编写的 webapp,它有一些屏幕,其中以时间间隔收集、分组和聚合来自多个表的数据。它基本上是一个类似于矩阵的大型 excel,其中我们在一个轴上以时间间隔聚合数据,而另一个轴上每个时间间隔的聚合数据的资源。它涉及许多内连接和左连接来收集所有数据,并且由于呈现数据的“报告”性质,我使用原始 sql 一起查询所有内容。

问题是多个用户可以在这些时间间隔内同时查看和编辑数据。与使用相同数据的其他用户相比,他们还可以在更精细或更粗糙的粒度上编辑数据,但在子/重叠间隔中。目前,当用户编辑某些数据时,会触发 django 请求,更改数据,将受影响的间隔再次聚合和分组并返回。但由于这些数据的易变性,其他用户可能在他们之前更改了某些内容。此外,每次对表格进行分组/聚合和重新呈现是一项非常繁重的操作(取决于数据量和间隔范围)。并发用户编辑时,情况会变得更糟。

我提出的解决方案:很明显,http 请求/响应机制对于这种事情并不理想;分组/聚合是相当重量级的,不适合每个请求执行此操作,理想情况下,并发将在用户之间传递,并且反馈应该像 googledocs 一样实时,而不是整页刷新。

我正在考虑制作一个守护进程,它根据请求从 dbms 读取感兴趣的平面数据并将其缓存在内存中。然后,对数据的所有更改都将发生在内存中,并写入 dbms。该守护进程通过锁引导对数据的访问,因此该守护进程可以处理哪些用户可以覆盖其他更改。

使用python代码对平面数据进行聚合和分组,只返回用户需要的切片;用户/守护进程通信将通过 websockets 运行。守护进程将提供一个订阅者/发布者通道,当某些事情发生变化时,对特定数据片段感兴趣的用户会收到通知。这个守护进程可以使用像 twisted 这样的框架来实现。但是我不确定事件驱动的方法在这里是否有效,因为我们想“引导”所有传入的请求......也许这些应该放在一个队列中并在单独的线程中运行?在我的调度程序旁边的线程中进行扭曲运行会更好,还是应该扭曲的主循环分离在该队列上工作的线程?我的理解是线程最适合 IO,而 python 繁重的代码基本上会阻塞其他线程。

有没有人做过类似的事情?

提前致谢!

卡尔

4

2 回答 2

3

Google 为现已废弃的 Wave 产品的并发编辑功能实施的方案已记录在案,http://www.waveprotocol.org/whitepapers/operational-transform。Wave 的这一方面似乎是成功的,尽管 Wave 本身很快就被抛弃了。

至于您提出的有关实施拟议方案的问题:

  1. 事件驱动系统完全有能力实现这个想法。事件驱动是组织代码的一种方式。它不会阻止您实现任何特定功能。
  2. 线程在很多情况下都不是最好的,尤其是在 Python 中。
    1. 它对于 CPU 密集型工作有很大的缺点,因为 CPython 一次只运行一个 Python 线程(不管可用的硬件资源如何)。这意味着多线程受 CPU 限制的 Python 程序通常不比单线程等效程序快,甚至更慢。
    2. 对于 IO,这个缺点的限制较小,因为 IO 不涉及在 CPython 上运行 Python 代码(IO API 都是用 C 实现的)。这意味着您可以同时在多个线程中执行 IO,因此线程化可能是一个好处。然而,在单个线程中同时执行 IO 正是 Twisted 的用途。与在单个线程中执行 IO 相比,线程没有任何好处,只要您以非阻塞方式(或者可能是异步方式)执行 IO。
  3. 你好世界。
于 2012-08-25T13:37:11.467 回答
2

我尝试了类似的方法,您可能对解决方案感兴趣。这是我的问题:

python Socket.IO 客户端,用于向 TornadIO2 服务器发送广播消息

这就是答案:

https://stackoverflow.com/a/10950702/675065

他还写了一篇关于解决方案的博客文章:

http://blog.y3xz.com/blog/2012/06/08/a-modern-python-stack-for-a-real-time-web-application/

软件堆栈包括:

我自己实现了这个,它就像一个魅力。

于 2012-08-25T10:51:31.287 回答