在需要可扩展的 Python 网络应用程序中解开大量数据是否可行?

Is it feasible to unpickle large amounts of data in a Python web app that needs to be scalable?

我正在开发我的第一个 web 应用程序。我在 Python 中使用 Flask 进行此操作,并且我想 运行 一段 Python 代码,该代码使用 Pickle 从几个 MB 的(二进制)文件中获取一个对象,其中包含所有必要的数据。有人告诉我,由于可扩展性,在 Web 应用程序中使用 Pickle 并不是一个好主意;为什么?

显然,出于特定目的,最好只获取必要的数据。但是,如果我使用 Elasticsearch 数据库并以最快的方式执行此操作,则整个过程花费的时间比我一次从二进制文件中获取所有数据要多大约 100 倍;一旦二进制文件被解开,最多需要一秒钟,计算速度非常快,所以我想知道我是否应该使用二进制文件,如果是这样,如何以可扩展的方式进行。

所以这也是我必须处理的事情。在我的情况下更糟,我的可能有 100 MB 或更多。

我的第一个问题是:

  • pickled 数据是否改变,如果改变,在哪里/由谁改变?

  • 您是否需要多组此类数据? (对我来说,不同的人在不同的时间需要 1000 个)

  • 多久需要一次?

这些问题的答案确实提出了处理它的不同方法。

假设你有一大堆请求需要的东西并且对每个人来说都是一样的,你知道你很快就会需要它 - 我会在应用程序启动时加载它并且将其保存在内存中或在首次请求时延迟加载(然后将其保存在内存中)。

另一种方法是将繁重的数据位拆分到自己的 Flask 应用程序中。

# api.py: your api flask application
from flask import Flask, jsonify, request

api_app = Flask(__name__)

big_gis_object = unpickle(...)

@api_app.route('/find_distance')
def find_distance():
    # grabbing the parameters for this request
    lat, lon = request.args['lat'], request.args['lon']

    # do your normal geo calculations here
    distance = big_gis_object.do_dist_calcs(lat, lon)

    # return the result as json to make things easy
    return jsonify(distance=distance)


# app.py: your main flask application
import requests
from flask import Flask, render_template

main_app = Flask(__name__)

@main_app.route('/')
def homepage():
    # this is how you ask the geo api app to do something for you
    # note that we're using the requests library do make it easier
    # - http://docs.python-requests.org/en/latest/user/quickstart/
    resp = requests.get('http://url_to_flask_app/find_distance', params=dict(lat=1.5, lon=1.7))
    distance = resp.json()['distance']
    return render_template('homepage.html', distance)

然后如何配置这些将取决于负载/要求。虽然它很灵活。例如,您的主要前端可以有 40 个进程,而只有 1 个 api 进程(尽管它一次只能做一件事)。如果您需要更多 api 流程,只需对其进行扩展,直到您获得适当的平衡。权衡是 api 进程需要更多内存。

这一切都有意义吗?

Pickle 文件是在 python 中加载数据的好方法。顺便考虑使用 C 实现:cPickle.

如果要缩放,请使用 pickle 文件。理想情况下,您希望寻找适合您的数据和项目需求的分区键。

例如,假设您有历史数据,您可以按日期创建一个 pickle 文件,而不是一个包含所有历史数据的文件。