如何缓存BULK_CREATE的单个Django rest API帖子?
问题描述
我有一个Django rest API端点。它接收JSON有效负载,例如
{ "data" : [0,1,2,3] }
在views.py函数中对其进行解码,并生成一个新的数据库对象,如so(伪代码):
newobj = MyObj.(col0 = 0, col1= 1, col2 = 2, col3 = 3)
newobj.save()
在测试中,创建x1000新对象的列表,然后执行批量创建的速度要快20倍:
Myobj.objects.bulk_create(newobjs, 1000)
所以,问题是,当我们有1000个帖子时,如何将单个帖子保存在Django中的某个位置,以便进行批量写入?
解决方案
感谢上面的回复,答案包括建议的部分内容,但这是一个超集,因此是摘要。
这实际上是关于创建FIFO。memcached被证明是不合适的(在尝试之后),因为只有redis具有启用此功能的列表功能,here进行了很好的解释。
还请注意,内置缓存Django不支持redis列表API调用。
因此我们需要一个新的docker-compose.yml条目来添加redis:
redis:
image: redis
ports:
- 6379:6379/tcp
networks:
- app-network
然后在views.py中添加:(请注意redisrpush的用法)
import redis
...
redis_host=os.environ['REDIS_HOST']
redis_port = 6379
redis_password = ""
r = redis.StrictRedis(host=redis_host, port=redis_port, password=redis_password, decode_responses=True)
...
def write_post_to_redis(request):
payload = json.loads(request.body)
r.rpush("df",json.dumps(payload))
因此,这会将接收到的有效负载推送到redis内存缓存中。我们现在需要读取(或弹出)它并将其写入postgres数据库。因此,我们需要一个每隔n秒唤醒并进行检查的进程。为此,我们需要Djangobackground_task。首先,使用以下命令安装:
pipenv install django-background-tasks
并添加到settings.py的已安装应用程序
INSTALLED_APPS = [
...
'background_task',
然后运行迁移以添加后台任务表:
python manage.py migrate
现在在views.py中,添加:
from background_task import background
from background_task.models import CompletedTask
并添加将缓存数据写入postgres数据库的函数,请注意装饰符,它声明应该每隔5秒在后台运行一次。另请注意redislpop的用法。
@background(schedule=5)
def write_cached_samples():
...
payload = json.loads(r.lpop('df'))
# now do your write of payload to postgres
... and delete the completed tasks or we'll have a big db leak
CompletedTask.objects.all().delete()
为了启动该进程,请在urls.py的基础上添加以下内容:
write_cached_samples(repeat=10, repeat_until=None)
最后,因为后台任务需要单独的进程,所以我们在docker-compose.yml中复制了Django docker容器,但将asgi服务器运行命令替换为后台进程运行命令。
django_bg:
image: my_django
command: >
sh -c "python manage.py process_tasks"
...
总而言之,我们添加了两个新的停靠容器,一个用于redis内存缓存,另一个用于运行Django后台任务。我们使用redis列表rPush和lop函数创建一个FIFO,并使用接收推送接口和后台任务弹出。
有一个小问题,其中nginx连接到了错误的Django容器,并通过停止并重新启动后台容器进行了更正,还有一些问题是Docker网络路由初始化错误。
下一步,我将Django HTTP API端点替换为Go One,看看我们的速度提高了多少,因为Daphne ASGI服务器达到了每秒仅100个请求的最大CPU。
相关文章