我怀疑这是否可能,但这是问题和建议的解决方案(建议的解决方案的可行性是此问题的目的):

我有一些“全局数据”,需要对所有请求可用。我将这些数据保存到Riak,并使用Redis作为访问速度的缓存层(目前...)。数据分为大约30个逻辑块,每个逻辑块约8 KB。

每个请求都需要读取这8KB块中的4个,从而从Redis或Riak读取32KB的数据。这是对任何特定于请求的数据的补充,这也需要读取(相当多的数据)。

假设每秒甚至有3000个请求(这不是实时服务器,因此我没有实数,但是3000ps是一个合理的假设,可能会更多),这意味着从Redis或Riak的ADDITION传输到96KBps的传输速度已经不存在-从应用程序逻辑进行的其他无关紧要的调用。此外,Python每秒将这些8KB对象的JSON解析3000次。

所有这一切-尤其是Python必须反复反序列化的数据-似乎完全是浪费,而一种完美的解决方案是将反序列化的数据仅缓存在Python的内存中 native 对象中,我可以在此之后定期刷新当所有这些“静态”数据变得陈旧时。在几分钟(或几小时)内一次,而不是每秒3000次。

但是我不知道这是否有可能。实际上,您实际上需要一个“始终运行”的应用程序来将其缓存在其内存中。而且我知道在nginx + uwsgi + python组合中不是这种情况(与之类的node相比)-python内存数据不会在我所知的所有请求中持久存在,除非我非常误解。

不幸的是,这是我“继承”的系统,因此无法对基本技术进行太多更改,我也不了解nginx + uwsgi + python组合在启动Python进程和持久化方面的工作方式Python内存中的数据-这意味着我可能会被上面的假设严重误解!

因此,关于此解决方案是否有效的直接建议+可以帮助我理解nginx + uwsgi + python如何在启动新进程和内存分配方面发挥作用的 Material 的引用将大有帮助。

附言:

  • 遍历了一些有关nginx,uwsgi等的文档,但是还没有完全理解我的用例所产生的后果。希望在此方面取得一些进展
  • 如果可以解决内存中的问题,我会拒绝Redis,因为我仅将上面提到的静态数据缓存在其中。这使进程内持久性内存中Python缓存对我来说更具吸引力,从而减少了系统中的一个移动部分,并且每个请求至少减少了四次网络往返。
  • 最佳答案

    您的建议并非直接可行。由于新流程可以在控件外部旋转,因此无法将 native Python数据保留在内存中。

    但是,有几种解决方法。

    通常,您只需要一层键值存储。有时,需要有固定大小的值缓冲区(您可以将它们直接用作str/bytes/bytearray对象;在那里需要struct或进行序列化的所有其他操作)就足够了。在这种情况下,uWSGI的内置caching framework将满足您的所有需求。

    如果需要更精确的控制,则可以查看如何在 SharedArea 上实现缓存并进行自定义。但是,我不建议这样做。它基本上为您提供了与文件相同的API,并且与仅使用文件相比,唯一的真正好处是服务器将管理文件的生存期。它适用于所有uWSGI支持的语言,甚至包括那些不允许文件的语言;并且可以在以后需要时更轻松地将自定义缓存迁移到分布式(多计算机)缓存。我认为这些都与您无关。

    另一种获取固定键值存储(但没有固定大小的缓冲区)的方法是使用Python的stdlib anydbm 。键值查找就如同它的pythonic一样:它看起来像dict,除了它已备份到磁盘上的BDB(或类似数据库)数据库之外,该数据库适本地缓存在内存中,而不是存储在内存中。内存哈希表。

    如果您需要处理其他一些简单类型(例如int s),那么这些类就非常容易解决/挑剔-您可能需要考虑使用 shelve

    如果您的结构足够僵化,则可以在顶层使用键值数据库,但可以通过ctypes.Structure访问值,或者使用struct进行反序列化。但是通常,如果您能做到这一点,那么您也可以消除顶层,这时您的整个工作仅仅是一个很大的StructureArray

    那时,您可以只使用一个普通文件进行存储-要么对其进行mmap(对于ctypes),要么对其进行openread(对于struct)。

    或使用multiprocessingShared ctypes Objects在共享存储区之外直接访问Structure

    同时,如果您实际上并不是一直都在需要所有缓存数据,而只是偶尔需要一点一点,那正是数据库的用途。同样,anydbm等可能就是您所需要的,但是如果您具有复杂的结构,请绘制一个ER图,将其变成一组表,然后使用类似MySQL的东西。

    10-02 03:05
    查看更多