Matrix impose une forte charge à Postgres
Par plusieurs biais, le service Matrix impose une forte charge à Postgres, qui a été jusqu'à bloquer le service pendant une journée du fait d'effets de bord.
Les principaux effets sont (à compléter au fur et à mesure) :
- Le nombre d'utilisateurs, de rooms, et le taux d'événements (10/s fédérés) sont dans l'absolu raisonnable mais commencent à coûter à niveau qui justifie de s'intéresser aux performances
- La complexité de certaines rooms (quelques dizaines, soit < 1% des rooms pour l'essentiel de la complexité du serveur) coûte particulièrement dans l'algorithme de gestion d'état, qui requête beaucoup en base et consomme du CPU en cas de recalcul d'état
- La suppression et le nettoyage continu du serveur (synatainer), en particulier de grosses rooms, génère des requêtes particulièrement longues en DELETE, qui remplissent le wal, s'exécutent sur plusieurs heures ou jours, et imposent des locks sur des centaines de milliers de lignes
- Matrix media repo (mmr) accumule des media depuis plusieurs années sans aucun garbage collecting, ce qui remplit des tables et des index en plus du S3
- mmr a un processus de garbage collection qui liste les media un par un par des SELECT individuels, chargeant un CPU du serveur à 100% pour postgres
Le dernier incident a été en particulier provoqué par les DELETE
générés par synatainer. Ils ont deux effets délétères principalement : 1. ils consomment des threads du threadpool d'accès à la base, et ralentissent doucement le serveur en causant des temps d'attente de thread bdd disponible puisque plus rares 2. ils s'étendent sur long en posant des locks sur des lignes, bloquant d'autres transactions.
Ce dernier cas a causé le blocage du script de migration de synapse à la mise à jour ce matin. Le DELETE
s'est poursuivi pendant l'upgrade, synapse en redémarrant a tenté un ALTER TABLE
sur la table lockée, bloqué par le DELETE
en cours depuis 3 jours, et synapse n'a pas démarré du fait de la migration bloquée.
En attendant d'avoir amélioré suffisamment la situation, il est possible de redémarrer postgres à tout moment sur le serveur sans effet majeur sur les applications :
cd /srv/core/db
docker-compose restart pg