python – 增加计数器并在超过阈值时触发操作
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 增加计数器并在超过阈值时触发操作,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2499字,纯文字阅读大概需要4分钟。
内容图文
![python – 增加计数器并在超过阈值时触发操作](/upload/InfoBanner/zyjiaocheng/723/57f44ec6749a49bcb66f18df6dcdaec0.jpg)
我有这样的模特
class Thingy(models.Model):
# ...
failures_count = models.IntegerField()
我有需要执行此操作的并发进程(Celery任务):
>做某种处理
>如果处理失败,则增加相应Thingy的failure_counter
>如果failures_counter超过某些Thingy的阈值,则发出警告,但只发出一个警告.
我有一些关于如何在没有竞争条件的情况下执行此操作的想法,例如使用显式锁定(通过select_for_update):
@transaction.commit_on_success
def report_failure(thingy_id):
current, = (Thingy.objects
.select_for_update()
.filter(id=thingy_id)
.values_list('failures_count'))[0]
if current == THRESHOLD:
issue_warning_for(thingy_id)
Thingy.objects.filter(id=thingy_id).update(
failures_count=F('failures_count') + 1
)
或者通过使用Redis(它已经存在)进行同步:
@transaction.commit_on_success
def report_failure(thingy_id):
Thingy.objects.filter(id=thingy_id).update(
failures_count=F('failures_count') + 1
)
value = Thingy.objects.get(id=thingy_id).only('failures_count').failures_count
if value >= THRESHOLD:
if redis.incr('issued_warning_%s' % thingy_id) == 1:
issue_warning_for(thingy_id)
两种解决方案都使用锁因为我正在使用PostgreSQL,有没有办法在没有锁定的情况下实现这一点?
我正在编辑问题以包含答案(感谢Sean Vieira,见下面的答案).问题是关于避免锁定的方法,这个答案是最佳的,因为它利用了multi-version concurrency control (MVCC) as implemented by PostgreSQL.
这个特定的问题明确允许使用PostgreSQL功能,虽然许多RDBMS实现UPDATE … RETURNING,但它不是标准的SQL,Django的ORM不支持开箱即用,所以它需要通过raw()使用原始SQL.相同的SQL语句将在其他RDBMS中工作,但每个引擎都需要自己讨论有关同步,事务隔离和并发模型(例如,带有MyISAM的MySQL仍然会使用锁).
def report_failure(thingy_id):
with transaction.commit_on_success():
failure_count = Thingy.objects.raw("""
UPDATE Thingy
SET failure_count = failure_count + 1
WHERE id = %s
RETURNING failure_count;
""", [thingy_id])[0].failure_count
if failure_count == THRESHOLD:
issue_warning_for(thingy_id)
解决方法:
据我所知,Django的ORM并不支持开箱即用 – 但是,这并不意味着它无法完成,你只需要深入到SQL级别(暴露在Django的ORM中)经理的raw method)使它工作.
如果您正在使用PostgresSQL> = 8.2,那么您可以使用RETURNING来获取failure_count的最终值而无需任何额外的锁定(数据库仍然会锁定,但只能设置该值足够长,没有额外的时间丢失与您通信):
# ASSUMPTIONS: All IDs are valid and IDs are unique
# More defenses are necessary if either of these assumptions
# are not true.
failure_count = Thingy.objects.raw("""
UPDATE Thingy
SET failure_count = failure_count + 1
WHERE id = %s
RETURNING failure_count;
""", [thingy_id])[0].failure_count
if failure_count == THRESHOLD:
issue_warning_for(thingy_id)
内容总结
以上是互联网集市为您收集整理的python – 增加计数器并在超过阈值时触发操作全部内容,希望文章能够帮你解决python – 增加计数器并在超过阈值时触发操作所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。