我正在编写一个相当复杂的Web应用程序。 Python后端运行一种算法,其状态取决于存储在几个相互关联的数据库表中的数据,这些数据表不经常更改,另外还有经常更改的用户特定数据。当用户使用应用程序时,算法的每用户状态会经历许多小的更改。在每个用户的工作中经常使用该算法来做出某些重要的决定。
出于性能原因,在(半规范化的)数据库数据的每个请求上重新初始化状态很快就变得不可行。例如,以某种方式缓存状态的Python对象是非常可取的,这样可以在必要时简单地使用和/或更新它。但是,由于这是一个Web应用程序,有几个进程处理请求,因此使用全局变量是不可能的。
我已经尝试序列化相关对象(通过pickle)并将序列化数据保存到DB,现在我正在尝试通过memcached缓存序列化数据。但是,这仍然会经常对序列化和反序列化对象产生很大的开销。
我查看了共享内存解决方案,但我发现的唯一相关内容是POSH。然而,POSH似乎并没有被广泛使用,我觉得将这样的实验组件集成到我的应用程序中并不容易。
我需要一些建议!这是我开发Web应用程序的第一步,所以我希望这是一个很常见的问题,有这些问题的众所周知的解决方案。在这一点上,假设Python后端在单个服务器上运行的解决方案就足够了,但也可以为扩展到多个服务器的解决方案提供额外的点数:)
注意:
答案 0 :(得分:8)
小心过早优化。
另外:“Python后端运行一个算法,其状态......”是Web框架中的会话。而已。让Django框架在缓存中维护会话状态。期。
“当用户使用应用程序时,算法的每用户状态会经历许多小的变化。”大多数Web框架都提供缓存的会话对象。通常它的性能非常高。请参阅Django的session documentation。
建议。 [修正]
看起来你有一些有用的东西。利用学习你的框架,学习工具,并学习你可以转动的旋钮,而不会流汗。具体来说,使用会话状态。
其次,摆弄缓存,会话管理以及易于调整的事情,看看你是否有足够的速度。通过试用它们来了解MySQL套接字或命名管道是否更快。这些是无编程优化。
第三,衡量绩效以找到实际的瓶颈。准备好提供(并保护)测量结果,使其足够精细,足以提供有意义的替代品比较。
例如,显示持久会话和缓存会话之间的性能差异。
答案 1 :(得分:3)
我认为multiprocessing框架在这里可能适用 - 即共享ctypes模块。
多处理对于Python来说是相当新的,因此它可能有一些奇怪之处。我不太确定该解决方案是否适用于未通过multiprocessing
生成的流程。
答案 2 :(得分:2)
我认为你可以给ZODB一个机会。
“ZODB的一个主要特性是透明性。您不需要编写任何代码来显式读取或写入数据库中的对象。您只需将持久对象放入一个像Python字典一样工作的容器中。这本词典中的所有内容都保存在数据库中。这个词典被认为是数据库的“根”。它就像一个魔术包;你放入其中的任何Python对象都会变得持久。“
最初它是Zope不可或缺的一部分,但最近也有一个独立的包。
它有以下限制:
“实际上对ZODB中存储的内容有一些限制。您可以将任何可以”腌制“的对象存储为标准的跨平台串行格式。列表,词典和数字等对象可以是pickled。文件,套接字和Python代码对象等对象无法存储在数据库中,因为它们无法被pickle。“
我已经阅读过了,但我自己并没有尝试过。
其他可能的事情可能是内存中的sqlite数据库,这可能会加快进程 - 作为内存数据库,但你仍然需要做序列化的东西。 注意:在内存中,db的资源很昂贵。
答案 3 :(得分:2)
首先,您的方法不是常见的Web开发实践。即使使用多线程,Web应用程序也可以运行多处理环境,既可扩展又易于部署。
如果您只需要初始化一个大对象,而不需要稍后更改,则可以通过使用在创建WSGI应用程序时初始化的全局变量或模块包含该对象来轻松完成加载等,多处理将为你做好。
如果您需要更改对象并从每个线程访问它,您需要确保您的对象是线程安全的,使用锁来确保。并使用单个服务器上下文,一个进程。任何多线程python服务器都能为您提供良好的服务,FCGI也是这种设计的不错选择。
但是,如果多个线程正在访问并更改您的对象,那么锁定可能会对您的性能提升产生非常不利的影响,这可能会使所有好处消失。
答案 4 :(得分:2)
这是Durus,一个用Python编写的应用程序的持久对象系统 编程语言。 Durus提供了一种使用和维护一致的简便方法 一个或多个进程使用的对象实例的集合。访问和更改 持久化实例通过包含的缓存Connection实例进行管理 commit()和abort()方法,以便更改是事务性的。
http://www.mems-exchange.org/software/durus/
我之前在一些研究代码中使用过它,我希望在某些计算中保留结果。我最终切换到pytables,因为它更好地满足了我的需求。
答案 5 :(得分:1)
另一种选择是检查状态的要求,听起来如果序列化是瓶颈,则对象非常大。你真的需要一个大的物体吗?
我知道在Stackoverflow播客27中,reddit讨论了他们用于状态的内容,所以听听可能很有用。