关于 celery 的应用场景问题
最近在学 celery,想用在一个 django 项目上,有些问题还没搞懂。
看到 celery 有一个应用场景是,解决高并发的请求任务,具体就是如果同一时间有多用户同时请求,这些请求会交给 celery 异步执行,用户不用等待,结果执行完会通知用户。那么 celery 是否可以解决并发操作数据库的问题?还是说这里的并发本质并不一样?
最近在学 celery,想用在一个 django 项目上,有些问题还没搞懂。
看到 celery 有一个应用场景是,解决高并发的请求任务,具体就是如果同一时间有多用户同时请求,这些请求会交给 celery 异步执行,用户不用等待,结果执行完会通知用户。那么 celery 是否可以解决并发操作数据库的问题?还是说这里的并发本质并不一样?
1. 用户发请求
2. 服务端接受处理
3. 服务端处理(花很长时间)
4. 用户收到结果
用 Celery 后:
1. 用户发请求
2. 服务端把接受请求
3. 服务端把要处理的函数以及参数丢到 task queue,并获得一个 task id (很快)
4. 用户收到 task id(您的请求已受理,但是还没有完成,但你可以用 task id 来查询结果,如果你不需要知道执行结果的话就不用再查了)
用户发多少请求用户说了算,但是具体什么时间真正处理这个请求里的操作服务端说了算。celery 比较适用于比较慢(不管是慢在 I/O 还是慢在 CPU )的操作,这种操作用户并不急着要结果,但是他在乎的是服务端收到这个请求,并且会在一定时间后完成这个操作。
如果是一个几秒内(不会积压一堆)就可以完成的慢操作,慢在 I/O 同时用户急着要(客户端同步在等待)
,那服务端用 asyncio 就可以同时更好支持多个用户并发,并不一定要用 celery, 用 celery 的话比较重了没必要。你说的数据库并发应该用 asyncio 去解决,可以理解为同一个进程内部做了个 celery 但是只适用于 I/O 慢的场景。如果不想写 asyncio 代码,只想写同步代码,那用 gevent 也可以。asyncio 的本质是把一个 blocking (阻塞) 的动作转换成 non-blocking (非阻塞):需要等待的时候不要让调用者等待,而是直接告诉调用者你先忙别的我还要一会儿才完事儿。
> 用户不用等待,结果执行完会通知用户。
通知这个过程默认是不存在的,还是得请求发起方凭 task id 去查询结果。或者实现一个对应的 [backend]( https://docs.celeryproject.org/en/stable/internals/reference/celery.backends.rpc.html) 让 celery 通知到这个地方。