Persistent in-memory Python object for nginx/uwsgi server

后端 未结 3 1308
粉色の甜心
粉色の甜心 2021-02-15 22:29

I doubt this is even possible, but here is the problem and proposed solution (the feasibility of the proposed solution is the object of this question):


I have

3条回答
  •  北海茫月
    2021-02-15 23:00

    What you're suggesting isn't directly feasible. Since new processes can be spun up and down outside of your control, there's no way to keep native Python data in memory.

    However, there are a few ways around this.

    Often, one level of key-value storage is all you need. And sometimes, having fixed-size buffers for values (which you can use directly as str/bytes/bytearray objects; anything else you need to struct in there or otherwise serialize) is all you need. In that case, uWSGI's built-in caching framework will take care of everything you need.

    If you need more precise control, you can look at how the cache is implemented on top of SharedArea and do something customize. However, I wouldn't recommend that. It basically gives you the same kind of API you get with a file, and the only real advantages over just using a file are that the server will manage the file's lifetime; it works in all uWSGI-supported languages, even those that don't allow files; and it makes it easier to migrate your custom cache to a distributed (multi-computer) cache if you later need to. I don't think any of those are relevant to you.

    Another way to get flat key-value storage, but without the fixed-size buffers, is with Python's stdlib anydbm. The key-value lookup is as pythonic as it gets: it looks just like a dict, except that it's backed up to an on-disk BDB (or similar) database, cached as appropriate in memory, instead of being stored in an in-memory hash table.

    If you need to handle a few other simple types—anything that's blazingly fast to un/pickle, like ints—you may want to consider shelve.

    If your structure is rigid enough, you can use key-value database for the top level, but access the values through a ctypes.Structure, or de/serialize with struct. But usually, if you can do that, you can also eliminate the top level, at which point your whole thing is just one big Structure or Array.

    At that point, you can just use a plain file for storage—either mmap it (for ctypes), or just open and read it (for struct).

    Or use multiprocessing's Shared ctypes Objects to access your Structure directly out of a shared memory area.

    Meanwhile, if you don't actually need all of the cache data all the time, just bits and pieces every once in a while, that's exactly what databases are for. Again, anydbm, etc. may be all you need, but if you've got complex structure, draw up an ER diagram, turn it into a set of tables, and use something like MySQL.

提交回复
热议问题