我怀疑这是否可能,但这是问题和建议的解决方案(建议的解决方案的可行性是此问题的目的):
我有一些“全局数据”,需要对所有请求可用。我将这些数据保存到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 的引用将大有帮助。
附言:
最佳答案
您的建议并非直接可行。由于新流程可以在控件外部旋转,因此无法将 native Python数据保留在内存中。
但是,有几种解决方法。
通常,您只需要一层键值存储。有时,需要有固定大小的值缓冲区(您可以将它们直接用作str
/bytes
/bytearray
对象;在那里需要struct
或进行序列化的所有其他操作)就足够了。在这种情况下,uWSGI的内置caching framework将满足您的所有需求。
如果需要更精确的控制,则可以查看如何在 SharedArea
上实现缓存并进行自定义。但是,我不建议这样做。它基本上为您提供了与文件相同的API,并且与仅使用文件相比,唯一的真正好处是服务器将管理文件的生存期。它适用于所有uWSGI支持的语言,甚至包括那些不允许文件的语言;并且可以在以后需要时更轻松地将自定义缓存迁移到分布式(多计算机)缓存。我认为这些都与您无关。
另一种获取固定键值存储(但没有固定大小的缓冲区)的方法是使用Python的stdlib anydbm
。键值查找就如同它的pythonic一样:它看起来像dict
,除了它已备份到磁盘上的BDB(或类似数据库)数据库之外,该数据库适本地缓存在内存中,而不是存储在内存中。内存哈希表。
如果您需要处理其他一些简单类型(例如int
s),那么这些类就非常容易解决/挑剔-您可能需要考虑使用 shelve
。
如果您的结构足够僵化,则可以在顶层使用键值数据库,但可以通过ctypes.Structure
访问值,或者使用struct
进行反序列化。但是通常,如果您能做到这一点,那么您也可以消除顶层,这时您的整个工作仅仅是一个很大的Structure
或Array
。
那时,您可以只使用一个普通文件进行存储-要么对其进行mmap
(对于ctypes
),要么对其进行open
和read
(对于struct
)。
或使用multiprocessing
的Shared ctypes
Objects在共享存储区之外直接访问Structure
。
同时,如果您实际上并不是一直都在需要所有缓存数据,而只是偶尔需要一点一点,那正是数据库的用途。同样,anydbm
等可能就是您所需要的,但是如果您具有复杂的结构,请绘制一个ER图,将其变成一组表,然后使用类似MySQL的东西。