Empecher la mise en cache

Bonjour,

Nous sommes passé récemment à ES2 et nous avons de gros problèmes de perf par rapport à ES1.7 (consommation CPU presque doublée et temps de réponse qui explose tout : ~20s contre 0.5s avant).

Après de multiple tests, nous avons déterminé que le problème venait de la mise en cache (au moins en partie). Avant il nous était possible de signaler si l'on désirait ou non qu'une partie de la query soit en cache. A présent, cela se base sur le type de la query (range, term, terms, etc) + sa présence dans les X dernières requêtes effectuées.

Y a-t-il moyen de retrouver cette personnalisation du cache dans la nouvelle structure des query ? Nous sommes en train de patcher Elasticsearch pour remettre le comportement de la 1.7 mais ça serait mieux si quelque chose était prévu de base.

Merci par avance.

Comment avez vous déterminé que le problème venait de la mise en cache? Aussi je ne suis pas certain de comprendre si le problème est que trop de queries sont mises en cache, ou pas assez? À quoi ressemblent les requêtes?

Par ailleurs, rétablir la capacité de configurer si oui ou non une partie de la requête doit être cachée ne va pas être simple.

Dans nos tests, ce que l'on a pu observer c'est qu'Elasticsearch passe son temps à faire de la place dans le cache pour mettre des nouvelles choses. Cependant, ce qu'il vient de virer est en fait utile et donc il reprend plus de CPU a recalculer ces éléments de la query pour les remettre en cache mais ils sont retirés du cache peu de temps après par des choses qui ne sont pas importantes une nouvelle fois. Et cela boucle non stop.

On a pu l'observer de la façon suivante :

  • On a deux projets :
    • le premier a besoin de cache sur une majorité de ses critères (les parties terms de la query).
    • le second n'a pas besoin de cache sur plusieurs de ses critères (on fait 4-5 req avec des morceaux de query identiques et ensuite ils auront changés).
  • Lorsqu'on a le premier projet en production : les temps de réponse sont corrects et l'utilisation du cache semble correcte (je présume qu'il y a une API pour savoir cela, c'est l'admin sys qui m'a redescendu l'info).
  • Lorsqu'on active le second projet en production : le CPU monte en flèche et les temps de réponse du premier projet passe de 0.5s à 20-25s.

On en a donc déduis que le second projet lance des requêtes qu'Elasticsearch place dans le cache constamment en supprimant le cache du premier projet qui lui même doit recalculer son cache continuellement. Dès qu'on désactive le second projet en production, il y a un petit moment de battement (quelques secondes) puis les temps de réponse redeviennent normaux pour le premier projet (le temps de finaliser la remise en cache de ses critères je présume).

Au niveau des requêtes :

  • Le premier projet :
    • principalement des match (+bool/must).
    • 2 bool -> must_not -> terms toujours présent (et où on souhaite du cache).
    • quelques terms où cela dépend de l'utilisateur mais 50% du temps se sont des choses communes aux utilisateurs donc on les veut en cache.
    • des aggrégations (terms uniquement).
  • Le second projet :
    • des match (+bool/must).
    • beaucoup de terms (avec des bool must/must_not) : certains sont communs à toutes les requêtes mais la majorité ne sont présents que pour 4-5 requêtes d'affilés puis ensuite les valeurs changes. On va avoir des terms pour chercher parmi une liste de status (integer), une liste de partenaires (string), etc.
    • quelques term pour chercher sur des champs contenant un boolean.
    • une range par moment

Parmi les retours que l'admin sys a pu trouver sur internet, notre hypothèse semble être correcte car d'autres personnes semblent avoir les mêmes problèmes que nous.

PS : On pense également qu'il est possible qu'il utilise plus de CPU à calculer 2-3 fois une query avant de décider de la mettre en cache alors qu'avant on pouvait lui dire de le faire dès la première requête.

Je ne suis pas complètement convaincu par l'analyse du problème. Pouvez vous regarder quelle est l'utilisation actuelle du cache en terme de mémoire? Est il au max? Si vous pouvez partager le nombre de cache hits et d'évictions, ça pourrait être intéressant également.

Vu les symptômes je pencherais plus pour un problème de cache du système de fichiers (géré par le système d'exploitation), qui est le facteur le plus importants de performance d'Elasticsearch. Pourriez vous communiquer le nombre de noeuds, la quantité mémoire totale de chaque noeud, la quantité de mémoire allouée à la JVM et la taille des indexes liés à ces deux projets (en incluant les replicas).

Bonjour, je prends le relais de mon collègue Christophe qui a ouvert le thread.

Nous avons 6 serveurs ayant chacun 1.2To de SSD et 128Go de RAM, 3 nodes par serveur soient 18 nodes. Chaque node a une pile de 20Go et indices.queries.cache.size configuré à 5Go. Il reste donc 68Go de RAM au minimum par serveur pour le cache du système de fichiers.

Les index liés aux deux projets sont identiques, ce sont les requêtes qui changent suivant le projet.
Nous avons donc 6 index:

  • 1 x index de 1G documents, 20 shards, ~1,2To en comptant 1 replica
  • 2 x index avec chacun 250M documents, 5 shards, ~160Go en comptant 1 replica
  • 3 x index avec chacun 35M documents, 5 shards, ~20Go en comptant 1 replica

En terme de cache avec seulement le premier projet d'actif, le pourcentage de hits est très faible (entre 5% et 7%), malgré un cache rempli (memory_size atteint 5Go, cache_size entre 8k et 10k). Les évictions atteignent environ 0.15% du total. A ce stade, ES 2.4 consomme environ 2 fois plus de CPU que ES 1.7.

Dès que l'on active le 2e projet, qui a une volumétrie de requêtes pourtant inférieure au premier, le cluster sature quasi instantanément en CPU, et le temps de réponse s'envole pour les deux projets.

Je n'ai pas sous la main les chiffres de cache lorsque le 2e projet est activé car nous sommes en ce moment en cours de test d'un patch (lucene + ES) permettant de forcer ou d'empêcher le cache d'une query et les chiffres ne seraient alors pas raccord avec la version vanilla.

Pour info, nos patchs:


Comme le disait mon collègue, il semble que nous ne soyons pas les seuls à subir une politique de cache qui ne correspond pas à nos besoins, cf. https://github.com/elastic/elasticsearch/issues/18680.
Par exemple, nous avons des cas d'utilisation où nous savons qu'il faut cacher une requête dès le premier appel car deux ou trois autres suivront immédiatement ensuite. Selon le type de requête c'est un pattern que le UsageTrackingCachingPolicy ne peut pas anticiper (dans le meilleur des cas il attend la 2e requête, mais plus généralement la 5e avant de cacher).

Pour faire suivre un peu notre histoire sur les perf Elasticsearch au cas où d'autres personnes soient dans notre situation :

  • Les modifications sur la mise en cache n'ont pas apportées de meilleurs perf.
  • Elasticsearch 5 étant disponible, nous avons essayé de migrer avec ce constat :
    1 - On constate une amélioration du temps de réponse par rapport à ES2.
    2 - On constate une nouvelle fois une augmentation de la charge CPU sur des index construit sur Elasticsearch 2.
    3 - On constate une augmentation de la charge CPU en plus si l'index est reconstruit en version 5 d'Elasticsearch.

Pour faire un résumé un peu grossier de notre constat (sans les chiffres totalement exacts) :

ES 1.7 : Charge CPU : 60%, temps de réponse inférieur à 600ms (moyenne)
ES 2.4 : Charge CPU : 110%, temps de réponse supérieur à 1s (moyenne)
ES 5.1 + index migré depuis la 2.4 : Charge CPU : 115%, temps de réponse inférieur à 700ms (moyenne)
ES 5.1 + index refait en ES 5.1 : Charge CPU : 120-125%, temps de réponse inférieur à 700ms (moyenne)

Après toutes les améliorations de performances vendues lors de ces 2 dernières années durant les Elastic{on}, on ne peut dire qu'une chose : déception totale.

Je conseille aux personnes désirant migrer vers ES 2 ou 5 de mettre les moyens pour faire des tests de charge grandeur réelle. Malgré les promesses lors des conférences, il reste de toutes évidences des problèmes de performances non résolus dans certains cas d'utilisations qui ne sont pas forcément les plus répandus et donc vérifiés avec les nouveaux bench mis en place pour ES5.