Technique

Optimiser Redis pour Logstash

Les files de messages sont utilisées dans les déploiements Logstash pour contrôler l'augmentation des événements, ce qui pourrait ralentir Elasticsearch et ses processus annexes. Redis est l'une des technologies permettant de générer une file de messages. Grâce à sa rapidité, sa facilité d'utilisation et ses faibles besoins en ressources, c'est également l'une des solutions les plus populaires.

C'est peut-être la raison pour laquelle cette solution est utilisée depuis longtemps — depuis la version 1.0.4 de Logstash, sortie il y a plus de 5 ans !

En raison des changements récents visant à améliorer le pipeline de Logstash — sans oublier les améliorations du plugin Redis lui-même —, il est possible que vous ne profitiez pas des performances optimales du plugin Redis pour Logstash.

Logstash cherche à déterminer le nombre de cœurs dans votre système et adapte le nombre d'outils de pipelining. Les pipelines n'améliorent que les tâches des plugins de filtrage et de sortie. Ils n'ont aucun effet sur les plugins d'entrée. Si vous n'avez pas choisi l'option « threads » dans le plugin d'entrée Redis, vous ne profitez que d'une fraction des performances optimales.

L'environnement de test inclut la version stable la plus récente de Logstash (2.3.4) avec Redis 3.0.7 sur la même machine (pour référence, un MacBook Pro 2015). La configuration utilisée pour Logstash est la suivante :

input {  
  redis {
    host => "127.0.0.1"
    data_type => "list"
    key => "redis_test"
    # batch_count => 1
    # threads => 1
  }
}
output { stdout { codec => dots } }

Lancez ceci avec bin/logstash -f some_config_file.config | pv -Wart > dev/null

Cet environnement de test n'est conçu que pour calculer le traitement maximal. Les performances réelles varient en fonction des autres plugins utilisés.

En essayant plusieurs options sur le paramètre threads et en laissant les autres paramètres à leur valeur par défaut, on obtient des résultats comme ceux-ci :

  • threads => 1 : 37.4K/sec
  • threads => 2 : 57K/sec
  • threads => 4 : 67K/sec
  • threads => 8 : 87.3K/sec

Recommencons ces tests en modifiant la valeur batch_count => 250 et en ajoutant -b 250 à notre ligne de commande Logstash pour tirer parti de l'augmentation :

  • threads => 1 : 35.2K/sec
  • threads => 2 : 48.9K/sec
  • threads => 4 : 58.7K/sec
  • threads => 8 : 72.5K/sec

Comme vous pouvez le voir, augmenter la valeur par défaut batch_count de 125 à 250 se traduit par une diminution de la performance.

Dans le passé, les utilisateurs travaillaient souvent avec une valeur élevée de batch_count avec Redis. Cette pratique n'est plus recommandée car elle réduit les performances. Le problème s'est aggravé avec les modifications de l'architecture de pipeline de Logstash. Une simple augmentation du batch_count à 250 résultats entraîne une baisse de performance de 89.5K/sec à 72.5K/sec quand threads => 8. La valeur optimale pour batch_count se situe autour de 125, qui est la valeur par défaut pipeline-batch-size (c'est pour une bonne raison !)

Détails des modifications

Les modifications récentes apportés à l'input Redis portent, notamment, sur l'activation par défaut du mode batch et sur l'utilisation d'un script Lua pour exécuter les commandes de récupération du batch sur le serveur Redis. Les scripts Lua agissent comme une transaction ; elles permettent de prendre en charge un batch et de raccourcir la file en une seule manipulation. Les autres connexions Redis sont mises en attente. Remarque : votre plugin de sortie Redis dans la configuration Logstash en amont est une connexion similaire.

Par ailleurs, n'oubliez pas que la façon dont les événements sont ajoutés à Redis par Logstash en amont peut affecter la performance de l'instance Logstash en aval. Par exemple, en préparant les résultats des tests, nous avons découvert qu'envoyer une requête sur la taille de la liste avec LLEN redis_test dans redis_cli affecte trop souvent les mesures. Essayez de comprendre ces facteurs dans votre instance Logstash en amont :

  • Le taux de génération des événements
  • La taille des événements : plus petits, plus importants et dans la moyenne
  • La taille des batch_events utilisés avec Redis en sortie

Vous souhaiterez peut-être envoyer un plus gros volume de batch_events 500, par exemple) en amont à Redis. Cela placera les événements en mémoire tampon avant l'intervention de Redis, et donnera peut-être aux threads d'entrée de Redis en aval le temps d'extraire l'information de Redis. Malheureusement, si le taux de génération des événements est élevé, la manœuvre ne sera peut-être pas aussi efficace : 50K/sec sur un batch de 500 signifie que la mémoire tampon du batch se remplit en 10 millisecondes.

Nous avons constaté que plus la taille des batchs est importante, moins le script Lua est performant. Concrètement, cela signifie que plus les batchs sont volumineux en entrée pour Redis, plus la performance des deux instances de Logstash de chaque côté de Redis sera faible.

En général, l'amélioration de la configuration du plugin d'entrée Redis, de la taille des batchs dans le pipeline et du nombre de threads permet de s'assurer que l'entrée est capable d'assurer un rythme correct pour l'étape de filtrage et de sortie. Renseignez-vous pour connaître la capacité de traitement moyenne de votre étape de filtrage et de sortie par défaut. Par exemple, si la capacité de traitement de votre étape de filtrage et de sortie est de 35K/sec, il n'est pas nécessaire de faire passer à 8 la valeur d'entrée vers Redis lorsqu'un ou deux threads actifs suffisent pour récupérer un nombre raisonnable d'événements par seconde.

Un autre variable est l'encodage JSON (1), le décodage (2) et l'encodage (3). Il y a trois étapes : la première dans la sortie Redis en amont, la deuxième dans l'entrée Redis en aval et la troisième dans l'envoi à Elasticsearch. Les événements volumineux en terme de taille de document JSON sont lents à décoder ; assurez-vous donc que votre environnement de test utilise des ensembles de données qui correspondent à votre volume et à la distribution d'un volume aussi proche que possible de votre production de données.

Mise à l'échelle des performances de traitement avec des instances Logstash multiples et un serveur Redis

De nombreux utilisateurs souhaitent améliorer les performances de traitement en démarrant de multiples instances Logstash sur différents appareils connectés au même serveur et à la même liste Redis.

Cette astuce peut se révéler efficace à condition d'appliquer la même configuration à chaque instance. Il est inutile de disposer de plusieurs entrées Redis avec des configurations différentes, à moins qu'elles ne soient connectées à d'autres serveurs Redis ou sur une liste différente. Alignez simplement vos threads sur une entrée Redis. Par exemple, avec 3 instances Logstash connectées au même serveur Redis, les connexions clientes peuvent entrer en conflit. Dès lors, il est conseillé de commencer par aligner une instance avant de réaligner les trois instances après lancement.

Conclusion

Notre but est d'améliorer l'entrée Redis en ajoutant un wrapper JRuby autour de la bibliothèque Java pour Redis, Jedis, un outil rapide et populaire. Cela permettra la prise en charge du mode Cluster de Redis !

En attendant, pour améliorer la performance de votre entrée Redis, essayez d'augmenter le nombre de threads. Assurez-vous aussi d'effectuer des mesures et des alignements corrects si vous utilisez d'autres valeurs que le batch_count par défaut, ou si vous utilisez plusieurs instances de Logstash sur un seul serveur Redis.

Si vous avez des questions sur Redis ou Logstash, n'hésitez pas à ouvrir un fil de discussion sur notre forum. Vous pouvez également nous retrouver sur IRC (#logstash) et sur GitHub.


Amusez-vous bien avec Logstash !