Оптимизация Django. 7 - Параллельные celery таски и их проблемы

Поділитися
Вставка
  • Опубліковано 6 січ 2023

КОМЕНТАРІ • 57

  • @Biongar
    @Biongar Рік тому +5

    docker system prune -a -f, очистит все, кроме volumes, а посмотреть все можно чреез команду docker system df

    • @jArkee777
      @jArkee777 Рік тому +1

      Спасибо большое, помогли очистить 3 гб памяти

    • @oooprya
      @oooprya 7 місяців тому

      Спасибо! Total reclaimed space: 16.67GB

  • @begula_chan
    @begula_chan 11 місяців тому +1

    Ох уж эти параллельные таски, с ними надо максимально аккуратно работать.
    Спасибо за еще одно чудесное видео!

  • @shaxzodnizamov9773
    @shaxzodnizamov9773 Рік тому +1

    Курс просто бомба !❤‍🔥

  • @alexey_all
    @alexey_all Рік тому +4

    Удалить неиспользуемые образы: docker rmi $(docker images -q -f dangling=true)
    Удалить контейнеры: docker rm $(docker ps -a -q -f status=exited)

  • @pylounge
    @pylounge 9 місяців тому +4

    Чтобы избежать копипаста в docker-compose можно использовать якоря (&) и ссылки (

  • @Keto-menu
    @Keto-menu Рік тому

    По поводу вашего вопроса. Как сделать так чтобы none не создавалось. Я в docker-compose после build вниз добавил image питона такой же как в Dockerfile. Вроде после этого перестает создаваться

  • @the_huge_knight
    @the_huge_knight 16 днів тому

    Можно в методе save() указать параметр update_fields в ф-ции set_price равный ('price', ) , в ф-ции set_comment равный ('comment', ). Тогда update в sql запросе не будет перезатирать все значения (можно чекнуть логи) объекта, а только указанные в update_fields. В данном случае эти 2 таски можно запустить параллельно.

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  16 днів тому +1

      Я просто взял этот кейс чтобы продемонстрировать проблему. В любом случае синглтон нужен , мы не можем всегда и везде это предусмотреть, особенно в немаленьких проектах

  • @belevich_andrei
    @belevich_andrei Рік тому +1

    Вероятно образы с именем 'None' создаются, когда мы делаем ребилд. Имя затирается, а старый образ становится None

  • @nikvityl
    @nikvityl Рік тому

    Спасибо большое, Узнал много нового, долго игрался с тасками, не обновлялся прайс, но почему-то когда создал новую подписку в ней все работало. Удалил старые и в новых все хорошо работает, очень интерсесно.

  • @user-rk1zj9ho5f
    @user-rk1zj9ho5f Рік тому

    Большое спасибо, крутые видосы

  • @unaibekovbakhyt6517
    @unaibekovbakhyt6517 Рік тому

    Благодарю

  • @user-mg1jj3mf9e
    @user-mg1jj3mf9e Рік тому +5

    как вариант, в таких не больших тасках, можно было бы просто использовать .save(update_fields=['comment'])

    • @user-qp7uv2ip7x
      @user-qp7uv2ip7x 10 місяців тому

      да, но поднятая проблема тоже актуальна, хотя ваше решение- снимает часть головной боли

  • @ramilelephant7826
    @ramilelephant7826 Рік тому

    Уже жду следующий выпуск , как в сериале залип

  • @user-gm8gh2gp2v
    @user-gm8gh2gp2v 6 місяців тому +1

    В asyncio таски ведь не уходят ни в другой поток, ни в другой процесс, они в едином цикле событий, который в одном потоке 00:53

  • @TitanicTiming13
    @TitanicTiming13 3 місяці тому

    Спасибо за видосы, одна маленькая просьбочка! Перед выгрузкой видео ускоряй его слегка, потому что лично мне ютубовского 2х мало для просмотра твоего контента))

  • @jackieuchiha7838
    @jackieuchiha7838 Рік тому +2

    Лучший канал по Django! Будут ли видосы про автоматизацию деплоя Django проекта через github actions + zero downtime deployment?

  • @jamjam3337
    @jamjam3337 3 місяці тому

    спасибо!😎

  • @noname52rus
    @noname52rus 7 місяців тому

    спасибо!

  • @dodokwak
    @dodokwak Рік тому +1

    Так много вкусного!

  • @ibrahimoglu
    @ibrahimoglu Рік тому

    👍

  • @user-mb9ml5hn9u
    @user-mb9ml5hn9u Рік тому +1

    Можно зайти в контейнер и там уже писать команды,так image не будут создаваться ,а результат будет тот же, хотел тебе ещё задать вопрос - а почему не пользуешься тайпхинтами?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  Рік тому +4

      Да, согласен, через docker exec вроде так же работает.
      Тайпхинты - мы много спорили с коллегами по этому вопросу. Мое мнения что питон хорош тем, что это минималистичный, легко-читаемый язык. Если его превращать в Java по синтаксису, он никак не получит сильные стороны от Java, скорее получит его недостатки. в 99% случаев тайпхинты не нужны, когда и так очевидно что это за тип по названию.
      Но это зависит от проекта, конечно. Где-то они будут в тему. А вообще это спорный вопрос, кто-то прям за них всегда топит.

  • @gonfrix9382
    @gonfrix9382 4 місяці тому

    а чем больше воркеров тем выше нагрузка на систему правильно? а если сам проект тяжелый? это же сильно по ресурсам бьет, есть ли альтернативные варианты выполнения тасков на такой случай?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  3 місяці тому

      Ну чем больше воркеров, тем больше запросов в базу, тем больше нагрузка на базу. Никак по-другому они систему не нагружают. Чтобы решить проблему нагрузки на базу лучше саму базу оптимизировать, добавить кеш, сделать еще read only базы и тд. Уменьшая количество Волкеров мы просто уменьшим производительность системы вцелом

  • @NRodriges
    @NRodriges Рік тому +1

    Доброго времени суток! Благодарю за прекрасные курсы!
    Возник вопрос - если в Celery длительность очереди может быть большая, к примеру, час, то с этим возникают некоторые проблемы:
    - Если сервер перезагрузится по какой либо причине, таски исчезнуть, а значит и вся информация, которая должна была обновится, не будет обновляться.
    - Если я выключу сервер для обновления версии софта, то будет та же проблема - все таски слетят.
    Я чего-то не так понял и этих проблем не существует или для них уже есть решения?

    • @BorisenkoV89
      @BorisenkoV89 Рік тому

      если я правильно понимаю, таски хранятся в Redis(БД) и селереи после перезапуска чекает редис.

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  Рік тому +1

      Да, я думаю что проблемы будут скорее с тасками, которые уже запущены и в процессе выполнения на момент перезагрузки . Вроде была какая-то опция чтобы celery их перезапускал после перезагрузки, надо посмотреть в доке

    • @NRodriges
      @NRodriges Рік тому

      @@BorisenkoV89Разве редис не очищается после перезагрузки системы?

  • @andreykuskov8807
    @andreykuskov8807 Рік тому

    Я не до конца понял необходимости добавления в запрос select_for_update? Зачем? Судя по доке, лочит строки в таблице, но мы вроде также используем менеджер transaction.atomic, который гарантирует, что операция будет выполнена полностью или не выполнена вовсе.... Можно пояснить подробнее про эту связку?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  Рік тому +1

      Это разные вещи. Atomic делает операцию атомарной, а select for update чтобы параллельные таски не пытались изменить объект , по тому что их изменения могут быть перезаписаны .
      На видео я опытным путем подтверждаю эту необходимость , если досмотреть до конца .

  • @vadimnikadon7332
    @vadimnikadon7332 Рік тому

    Привет. Можно ли решить проблему параллелизма изменив уровень изоляции транзакций в самой бд? Например поставить repeatable read?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  Рік тому

      Привет. Ну в видео я показал два варианта: без трансакции и с ней. И то, как трансакция решает показанную проблему.
      Уровни изоляции они присутствуют в трансакциях. Без них не существуют.
      Тут же проблема что мы создали объект кода python , и он устарел , пока мы что-то делали , а потом мы его сохранили и он перезатер. Вообщем это немного другая ситуация.

  • @user-kn5ip9lr6r
    @user-kn5ip9lr6r 6 місяців тому

    А зачем мы используем transaction.atomic? Ведь select_for_update уже блокирует объекты модели для использования другим воркером. Если сделать то же самое без transaction.atomic, что изменится?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  6 місяців тому

      Select for update не работает вне transaction

    • @user-kn5ip9lr6r
      @user-kn5ip9lr6r 6 місяців тому

      @@SeniorPomidorDeveloper спасибо большое что отвечаете всем нам

  • @1978rembo
    @1978rembo Рік тому +1

    Уроки по FastApi есть в планах ?

  • @dotco22
    @dotco22 Рік тому +1

    Столкнулся с проблемой, что из двух задач всегда выполнялась только одна. Никак кроме удаления Singleton решить не смог

  • @user-kn5ip9lr6r
    @user-kn5ip9lr6r 7 місяців тому

    Почему когда вы добавили транзакции и воркеры разобрали таски, один таск закончился намного раньше и не ждал 20+27 секунд? Куда делись эти самые sleep?

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  7 місяців тому

      А в каком моменте видео это было?

    • @user-kn5ip9lr6r
      @user-kn5ip9lr6r 7 місяців тому

      ​@@SeniorPomidorDeveloperна 25:05. И потом ещё вы говорите: "видно, что одна таска отработала значительно быстрее"

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  7 місяців тому

      Скорее всего на монтаже видео так неудачно подрезал. Там вроде дольше должен быть sleep , да

    • @user-kn5ip9lr6r
      @user-kn5ip9lr6r 7 місяців тому

      @@SeniorPomidorDeveloper понятно. Спасибо большое. Отлично объясняете.

    • @SeniorPomidorDeveloper
      @SeniorPomidorDeveloper  7 місяців тому

      @user-kn5ip9lr6r спасибо что смотрите!

  • @ioannchimrov
    @ioannchimrov Рік тому

    попробуй запускать команды в нужном контейнере через следующую команду: "docker-compose exec containe_name some_command_in_container" и в этом случае не будет создаваться новый контейнер

  • @rostislavk3230
    @rostislavk3230 5 місяців тому

    а где можно исходные коды посмотреть?

  • @the_codest
    @the_codest 10 місяців тому

    Еще раз спасибо! Офигенный разбор! 👍👍👍
    Правда, у меня косяк не воспроизводится, 😄 видимо, потому что я пошел путем апдейтов, а не сейвов:
    def set_price_from_service(service_instance_id):
    from .models import Subscription, Service
    time.sleep(10)
    service_instance = Service.objects.get(id=service_instance_id)
    queryset = service_instance.subscriptions.select_related('plan').only('plan__discount_percent', 'service_id')
    subscriptions = []
    for i_subscription in queryset:
    new_price = service_instance.price - service_instance.price * i_subscription.plan.discount_percent / 100
    i_subscription.price = new_price
    subscriptions.append(i_subscription)
    Subscription.objects.bulk_update(subscriptions, fields=['price'])
    @shared_task()
    def set_comment(service_instance_id):
    from .models import Subscription, Service
    service_instance = Service.objects.get(id=service_instance_id)
    queryset = service_instance.subscriptions.all()
    subscriptions = []
    for i_subscription in queryset:
    i_subscription.comment = str(datetime.datetime.now())
    subscriptions.append(i_subscription)
    time.sleep(20)
    Subscription.objects.bulk_update(subscriptions, fields=['comment'])