Sidekiq بطيء + Postmaster يستهلك أكثر من 95% من وحدة المعالجة المركزية (32 نواة) بعد ترقية إصدار PostgreSQL

لذا قمت اليوم بترقية النظام، ويبدو أن إصدار PostgreSQL قد تم تحديثه خلال العملية. منذ ذلك الحين، عاد هذا المشكلة (أو مشكلة مشابهة) (الموضوع القديم مغلق الآن):

جربت ما حل هذه المشكلة سابقًا:

cd /var/discourse/
./launcher enter app
sudo -u postgres psql
\c discourse
VACUUM FULL VERBOSE;

وكذلك:

REINDEX DATABASE discourse;

لكن دون جدوى :upside_down_face:

يستخدم Postmaster ما بين 95% و100% من 32 نواة معالج. Sidekiq يعمل بسرعة تقريبًا وظيفة واحدة في الثانية.

كما جربت تفريغ Redis وإعادة البناء من جديد. وقد اختبرت بين 12 و8 و4 من وحدات Unicorn Sidekiq وUnicorn Workers.

كان النظام يعمل بشكل متين وسلس تمامًا قبل ترقية PostgreSQL باستخدام 12 وحدة Unicorn Workers وSidekiqs. حاليًا أعمل بالإصدار 2.5.0.beta5، وأعتقد أنني كنت أعمل بالإصدار 2.5.0.beta2 قبل التحديث.

:firstworldproblem:

تحتاج إلى التحقق من الاستعلامات الدقيقة التي ينفذها PostgreSQL حتى نتمكن من تقديم اقتراحات.

تفعيل pg_stat_statements مفيد جدًا لهذا الغرض.

شكرًا لك @Falco - إليك بعض الإحصائيات، وأخبرني إذا كنت بحاجة إلى رؤية المزيد من الاستعلامات حيث يتم قطعها في النهاية.

                                                                                                                                                     الاستعلام                                                                                                                                                     | الوقت_الإجمالي | عدد_النداءات |   الحد_الأدنى   |  المتوسط   |    الحد_الأعلى    | نسبة_وحدة_المعالجة
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+-------+---------+---------+-----------+---------
SELECT "posts"."id", "posts"."user_id", "posts"."topic_id", "posts"."post_number", "posts"."raw", "posts"."cooked", "posts"."created_at", "posts"."updated_at", "posts"."reply_to_post_number", "posts"."reply_count", "posts"."quote_count", "posts"."deleted_at", "posts"."off_topic_count", "posts"."like | 4018799.92 |  2031 | 1458.34 | 1978.73 |   2690.51 |   38.90
SELECT COUNT(*) FROM "posts" WHERE ("posts"."deleted_at" IS NULL) AND (posts.post_type IN ($1,$2,$3)) AND (post_number > COALESCE(( SELECT last_read_post_number FROM topic_users tu WHERE tu.user_id = $4 AND tu.topic_id = $5 ),$6)) AND (reply_to_user_id = $7 OR exists( SELECT $8 from topic_users tu W | 3959915.35 |  2021 | 1467.53 | 1959.38 |   2753.25 |   38.33
SELECT COUNT(*) FROM "posts" INNER JOIN "topics" ON "topics"."id" = "posts"."topic_id" AND ("topics"."deleted_at" IS NULL) WHERE ("posts"."deleted_at" IS NULL) AND (topics.category_id = $1) AND (topics.visible = $2) AND (posts.deleted_at IS NULL) AND (posts.user_deleted = $3) AND (topics.id <> $4) A |  349840.54 |   148 |   55.14 | 2363.79 | 111182.89 |    3.39
SELECT "posts"."id" FROM "posts" WHERE ("posts"."deleted_at" IS NULL) AND "posts"."topic_id" = $1 AND (posts.user_id = $2 OR post_type IN ($3,$4,$5)) AND "posts"."post_number" = $6 LIMIT $7                                                                                                                |  237109.72 |   123 | 1488.37 | 1927.72 |   2387.02 |    2.30
SELECT "posts"."id", "posts"."user_id", "posts"."topic_id", "posts"."post_number", "posts"."raw", "posts"."cooked", "posts"."created_at", "posts"."updated_at", "posts"."reply_to_post_number", "posts"."reply_count", "posts"."quote_count", "posts"."deleted_at", "posts"."off_topic_count", "posts"."like |  223843.91 |   560 |  269.46 |  399.72 |    522.30 |    2.17
SELECT "posts"."id", "posts"."user_id", "posts"."topic_id", "posts"."post_number", "posts"."raw", "posts"."cooked", "posts"."created_at", "posts"."updated_at", "posts"."reply_to_post_number", "posts"."reply_count", "posts"."quote_count", "posts"."deleted_at", "posts"."off_topic_count", "posts"."like |  222330.42 |   113 | 1516.53 | 1967.53 |   2620.96 |    2.15
SELECT l.post_id, l.url, l.clicks, COALESCE(t.title, l.title) AS title, l.internal, l.reflection, l.domain FROM topic_links l LEFT JOIN topics t ON t.id = l.link_topic_id LEFT JOIN categories AS c ON c.id = t.category_id WHERE (t.deleted_at IS NULL) AND (COALESCE(t.archetype, $1) <> $2) AND (l.post_ |   77597.13 |   134 |  479.18 |  579.08 |    662.30 |    0.75
SELECT "posts"."id", EXTRACT($1 FROM CURRENT_TIMESTAMP - created_at)::INT AS days_ago FROM "posts" WHERE ("posts"."deleted_at" IS NULL) AND "posts"."topic_id" = $2 AND (posts.user_id = $3 OR post_type IN ($4,$5,$6)) ORDER BY "posts"."sort_order" ASC                                                    |   57100.18 |   131 |  285.36 |  435.88 |    545.55 |    0.55
SELECT MAX("posts"."post_number") FROM "posts" WHERE ("posts"."deleted_at" IS NULL) AND "posts"."topic_id" = $1 AND (posts.user_id = $2 OR post_type IN ($3,$4,$5))                                                                                                                                          |   56887.08 |   131 |  285.22 |  434.25 |    534.65 |    0.55
SELECT COALESCE(SUM(rs.score), $1) AS total_spam_score, COUNT(DISTINCT rs.user_id) AS spam_user_count FROM reviewables AS r INNER JOIN reviewable_scores AS rs ON rs.reviewable_id = r.id WHERE r.target_created_by_id = $2 AND rs.reviewable_score_type = $3 AND rs.status IN ($4, $5)                      |   16211.73 |   119 |   86.25 |  136.23 |    163.52 |    0.16
SELECT COUNT(*) FROM "topics" WHERE ("topics"."deleted_at" IS NULL) AND "topics"."category_id" = $1 AND "topics"."visible" = $2 AND (topics.id <> $3) AND (topics.created_at > $4)                                                                                                                           |   14922.91 |   152 |   61.68 |   98.18 |    154.13 |    0.14
SELECT COUNT(*) FROM "users" INNER JOIN "topic_allowed_users" ON "users"."id" = "topic_allowed_users"."user_id" WHERE "topic_allowed_users"."topic_id" = $1                                                                                                                                                  |   14358.68 |   186 |    9.17 |   77.20 |    109.96 |    0.14
SELECT ftl.url, COALESCE(ft.title, ftl.title) AS title, ftl.link_topic_id, ftl.reflection, ftl.internal, ftl.domain, MIN(ftl.user_id) AS user_id, SUM(clicks) AS clicks FROM topic_links AS ftl LEFT JOIN topics AS ft ON ftl.link_topic_id = ft.id LEFT JOIN categories AS c ON c.id = ft.category_id WHERE |   14029.70 |   186 |   12.82 |   75.43 |     94.01 |    0.14
SELECT COUNT(*) FROM ( SELECT $1 FROM notifications n LEFT JOIN topics t ON t.id = n.topic_id WHERE t.deleted_at IS NULL AND n.high_priority = $2 AND n.user_id = $3 AND n.id > $4 AND NOT read LIMIT $5 ) AS X                                                                                              |    3364.46 |  3790 |    0.02 |    0.89 |      3.21 |    0.03
SELECT * FROM ( SELECT n.id, n.read FROM notifications n LEFT JOIN topics t ON n.topic_id = t.id WHERE t.deleted_at IS NULL AND n.high_priority AND n.user_id = $1 AND NOT read ORDER BY n.id DESC LIMIT $2 ) AS x UNION ALL SELECT * FROM ( SELECT n.id, n.read FROM notifications n LEFT JOIN topics t ON  |     968.26 |  3654 |    0.06 |    0.26 |      1.04 |    0.01
SELECT tags.name as tag_name, SUM(stats.topic_count) AS sum_topic_count FROM category_tag_stats stats JOIN tags ON stats.tag_id = tags.id AND stats.topic_count > $1 WHERE stats.category_id in ($2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30 |     953.21 |   173 |    3.57 |    5.51 |      7.52 |    0.01
SELECT a.attname FROM ( SELECT indrelid, indkey, generate_subscripts(indkey, $1) idx FROM pg_index WHERE indrelid = $2::regclass AND indisprimary ) i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = i.indkey[i.idx] ORDER BY i.idx                                                           |     657.76 |   163 |    0.01 |    4.04 |      8.66 |    0.01
SELECT $1 AS one FROM "push_subscriptions" WHERE "push_subscriptions"."user_id" = $2 LIMIT $3                                                                                                                                                                                                                |     381.25 |  2029 |    0.10 |    0.19 |      0.41 |    0.00
INSERT INTO "notifications" ("notification_type", "user_id", "data", "created_at", "updated_at", "topic_id", "post_number") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"                                                                                                                               |     339.56 |  2028 |    0.08 |    0.17 |      0.94 |    0.00
SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2                                                                                                                                                                                                                                               |     313.51 |  7521 |    0.02 |    0.04 |      0.16 |    0.00

ملاحظة سريعة فقط: أعاني من نفس المشكلة، وللأسف ليس لدي خبرة في PostgreSQL. إذا كنت سأبحث في مكان ما، فستكون هناك حاجة إلى تعليمات أكثر تفصيلاً. عذراً.

هل يمكنك تجربة أمر vacuum verbose analyze؟ ينطبق هذا أيضًا عليك يا @eboehnisch. الاستعلام التالي البسيط جدًا والذي يستغرق في المتوسط ثانيتين غريب جدًا:

كما ذُكر في موضوع تحديث PostgreSQL 12، فإن إنشاء الإحصائيات فكرة جيدة بعد التحديث.

جربت أمر VACUUM VERBOSE ANALYZE;. ما الذي يجب أن أبحث عنه في النتائج؟

رائع، شكرًا لك! أعتقد أن هذا قد حل مشكلة تزايد استخدام وحدة المعالجة المركزية من قبل مسؤولي البريد. لذا فإن هذا تحسين كبير.

لا يزال Sidekiq بطيئًا للأسف، لكنه أفضل مما كان عليه قبل تشغيل أمر VACUUM VERBOSE ANALYZE;

لا يوجد شيء خاص، إلا إذا كانت هناك رسالة خطأ كبيرة.

يجب أن تتعافى الأداء الآن.

يا له من رائع!

يجب أن يكون قادرًا على الفوز في السباق ومعالجة الطابور في النهاية الآن.

هذا بالتأكيد حسّن الوضع، لكن بعد فترة، بدأت ثلاث عمليات postmaster مرة أخرى في استهلاك 100% من وحدة المعالجة المركزية لمدة تزيد عن دقيقة لكل منها.

أقترح الانتظار قليلاً، لأنك ربما لديك طابور للمعالجة من الفترة البطيئة. تحقق من /sidekiq للحصول على الإحصائيات.

:smiley: لقد تسارعت السرعة حقًا الآن، ويبدو أن المشكلة قد حُلت. شكرًا جزيلاً لك على المساعدة يا @Falco! سأتركها تعمل لبعض الوقت وسأقوم بنشر تحديث هنا لاحقًا~

ربما يمكنك تجربة تشغيل:

VACUUM FULL VERBOSE;

و(بافتراض أن اسم قاعدة بياناتك هو ‘discourse’ وهو الافتراضي):

REINDEX DATABASE discourse;

قد يكون هذا أفضل من إعادة الفهرسة العادية، لكنني لم أجربه: PostgreSQL 12 update

تولّد العمليتان المذكورتان أعلاه أقفالًا قد تكون صعبة التطبيق على موقع حي. أنصح بالعمليات المدرجة في post-update-optional-tasks لأنها، بخلاف استهلاكها لكثير من وحدة المعالجة المركزية، لا تعيق عمليات قاعدة البيانات العادية.

شغّل كلا الأمرين. ومع ذلك، يُبلغ الأمر الثاني عن خطأ:

discourse=# REINDEX SCHEMA CONCURRENTLY public;
ERROR:  could not create unique index "index_users_on_username_lower_ccnew"
DETAIL:  Key (username_lower)=(marks) is duplicated.

أعتقد أن الوقت قد حان للدخول إلى PostgreSQL والبحث عن السجل وحذفه.

أدى عملية التفريغ (vacuum) إلى حل المشكلة إلى حد ما، لكنني ما زلت ألاحظ قممًا كل بضع دقائق حيث تستهلك عملية واحدة إلى ثلاث عمليات postmaster وحدة المعالجة المركزية لمدة دقيقة أو دقيقتين لكل منها. لذا، أعتقد أن هناك المزيد من المشكلات.

هل من الممكن العودة إلى PostgreSQL 10؟

بالتأكيد، إذا كان لديك نسخة احتياطية من قبل الترقية. ومع ذلك، ستفقد كل ما تم إنشاؤه منذ أخذ النسخة الاحتياطية.

من الأفضل على الأرجح تحديد جذر هذه المشكلات، حيث أصبحت Postgres12 الآن معيارًا لأي تثبيت جديد.

لا، هذا غير ممكن… نحن ننتقل بشكل دائم إلى PG12.

انظر:

حسنًا، للمتابعة، يبدو أن كل شيء على ما يرام؛ فقد هدأ postmaster بشكل كبير، ويعمل sidekiq بسرعة كبيرة مرة أخرى.

ملخص لما نجح في سيناريوهي (مع اسم قاعدة البيانات الافتراضي ‘discourse’):

cd /var/discourse/
./launcher enter app
sudo -u postgres psql
\c discourse

ثم من وحدة تحكم postgres، تم تنفيذ كل من الأوامر التالية. يستغرق كل أمر بعض الوقت للتنفيذ، اعتمادًا على حجم قاعدة البيانات، مع استهلاك عالي لمعالج CPU في الأمرين الأولين أيضًا:

VACUUM FULL VERBOSE;

REINDEX DATABASE discourse;

VACUUM VERBOSE ANALYZE;

ملاحظة: لم ألاحظ أي فرق حتى تم تنفيذ أمر VACUUM VERBOSE ANALYZE; كما أوصى @Falco، لذا قد لا يكون الأمران الأولان ضروريين. ومع ذلك، بدا أن الأمرين الأولين هما المفتاح لحل هذه المشكلة في الماضي في إصدار Postgresql السابق.

إذا حصلت على خطأ مثل ‘ERROR: deadlock detected’ أثناء تنفيذ REINDEX DATABASE discourse; - فحاول ببساطة تشغيله مرة أخرى حتى يعمل. حدث لي هذا في المرة السابقة (في إصدار Postgresql السابق).

هناك بعض التوصيات بتشغيل إعادة فهرسة متزامنة بدلاً من إعادة الفهرسة المذكورة أعلاه: PostgreSQL 12 update

ومع ذلك، لاحظ أن @eboehnisch المذكور أعلاه تلقى خطأً من إعادة الفهرسة المتزامنة، انظر أعلاه.

لقد شهدنا حدوث هذا الأمر مرات كافية في عمليات الانتقال المختلفة، لذا أعتقد أنه ينبغي إضافته إلى سكريبت الهجرة @Falco

أعلم أنه يُبطئ الأمور بشكل ملحوظ، لكنه يستحق العناء وسيقلل من طلبات الدعم.

ملاحظة… كلمة VERBOSE هناك تعني ببساطة أنها تُظهر المخرجات أثناء التنفيذ… الشيء الكبير المفقود كان VACUUM ANALYZE. إعادة الفهرسة تتعلق في الغالب باستعادة المساحة.