sql >> Database >  >> NoSQL >> MongoDB

Schrijf je eerste adviseur

Heb je je ooit afgevraagd wat het advies in ClusterControl veroorzaakt dat je schijf vol raakt? Of het advies om primaire sleutels aan te maken op InnoDB-tabellen als ze niet bestaan? Deze adviseurs zijn miniscripts die zijn geschreven in de ClusterControl Domain Specific Language (DSL), een Javascript-achtige taal. Deze scripts kunnen worden geschreven, gecompileerd, opgeslagen, uitgevoerd en gepland in ClusterControl. Dat is waar de blogserie van ClusterControl Developer Studio over gaat.

Vandaag behandelen we de basisprincipes van Developer Studio en laten we u zien hoe u uw allereerste adviseur kunt maken, waarbij we twee statusvariabelen zullen kiezen en advies geven over hun resultaat.

De adviseurs

Adviseurs zijn miniscripts die door ClusterControl worden uitgevoerd, op aanvraag of volgens een planning. Ze kunnen van alles zijn, van eenvoudig configuratieadvies, waarschuwing bij drempels of complexere regels voor voorspellingen of clusterbrede automatiseringstaken op basis van de status van uw servers of databases. Over het algemeen voeren adviseurs meer gedetailleerde analyses uit en produceren ze uitgebreidere aanbevelingen dan waarschuwingen.

De adviseurs worden opgeslagen in de ClusterControl-database en u kunt nieuwe adviseurs toevoegen of bestaande adviseurs wijzigen/wijzigen. We hebben ook een Github-repository voor adviseurs waar u uw adviseurs met ons en andere ClusterControl-gebruikers kunt delen.

De taal die wordt gebruikt voor de adviseurs is de zogenaamde ClusterControl DSL en is een gemakkelijk te begrijpen taal. De semantiek van de taal kan het beste worden vergeleken met Javascript met een paar verschillen, waarbij de belangrijkste verschillen zijn:

  • Puntkomma's zijn verplicht
  • Verschillende numerieke gegevenstypen zoals gehele getallen en niet-ondertekende lange lange gehele getallen.
  • Arrays zijn tweedimensionale en enkeldimensionale arrays zijn lijsten.

U vindt de volledige lijst met verschillen in de ClusterControl DSL-referentie.

De Developer Studio-interface

De Developer Studio-interface is te vinden onder Cluster> Beheren> Developer Studio. Dit opent een interface zoals deze:

Adviseurs

De adviseurs-knop genereert een overzicht van alle adviseurs met hun output sinds de laatste keer dat ze werden uitgevoerd:

U kunt ook het schema van de adviseur in crontab-formaat zien en de datum/tijd sinds de laatste update. Sommige adviseurs zijn gepland om slechts één keer per dag te werken, dus hun advies weerspiegelt mogelijk niet langer de realiteit, bijvoorbeeld als u het probleem waarvoor u bent gewaarschuwd al hebt opgelost. U kunt de adviseur handmatig opnieuw starten door de adviseur te selecteren en uit te voeren. Ga naar het gedeelte "compileren en uitvoeren" om te lezen hoe u dit doet.

Adviseurs importeren

Met de knop Importeren kunt u een tarball importeren met nieuwe adviseurs erin. De tarball moet relatief aan het hoofdpad van de adviseurs worden gemaakt, dus als u een nieuwe versie van het MySQL-querycachegrootte-script (s9s/mysql/query_cache/qc_size.js) wilt uploaden, moet u de tarball starten uit de s9s-directory.

Exporterende adviseurs

U kunt de adviseurs of een deel ervan exporteren door een knooppunt in de boomstructuur te selecteren en op de knop Exporteren te drukken. Dit zal een tarball maken met de bestanden in het volledige pad van de gepresenteerde structuur. Stel dat we een back-up willen maken van de s9s/mysql-adviseurs voordat we een wijziging aanbrengen, dan selecteren we gewoon de s9s/mysql-node in de boomstructuur en drukken op Exporteren:

Opmerking:zorg ervoor dat de s9s-map aanwezig is in /home/myuser/.

Dit maakt een tarball genaamd /home/myuser/s9s/mysql.tar.gz met een interne directorystructuur s9s/mysql/*

Een nieuwe adviseur maken

Omdat we export en import hebben gedekt, kunnen we nu beginnen met experimenteren. Dus laten we een nieuwe adviseur maken! Klik op de knop Nieuw om het volgende dialoogvenster te krijgen:

In dit dialoogvenster kunt u uw nieuwe adviseur maken met een leeg bestand of het vooraf vullen met de Galera- of MySQL-specifieke sjabloon. Beide sjablonen voegen de benodigde include (common/mysql_helper.js) en de basis toe om de Galera- of MySQL-knooppunten op te halen en eroverheen te lussen.

Een nieuwe adviseur maken met de Galera-sjabloon ziet er als volgt uit:

#include "common/mysql_helper.js"

Hier kunt u zien dat de mysql_helper.js wordt opgenomen om de basis te bieden voor het verbinden en opvragen van MySQL-knooppunten.

Dit bestand bevat functies die u indien nodig kunt aanroepen, zoals bijvoorbeeld readVariable(,) waarmee u de waarde van de globale variabelen kunt krijgen of readStatusVariable(,) waarmee u ook om de globale statusvariabelen in MySQL te krijgen. Dit bestand bevindt zich in de boomstructuur zoals hieronder te zien is:

var WARNING_THRESHOLD=0;
…
if(threshold > WARNING_THRESHOLD)

De waarschuwingsdrempel is momenteel ingesteld op 0, wat betekent dat als de gemeten drempel groter is dan de waarschuwingsdrempel, de adviseur de gebruiker moet waarschuwen. Houd er rekening mee dat de variabele drempel nog niet is ingesteld/gebruikt in de sjabloon, omdat dit een kickstart is voor uw eigen adviseur.

var hosts     = cluster::Hosts();
var hosts     = cluster::mySqlNodes();
var hosts     = cluster::galeraNodes();

De bovenstaande instructies halen de hosts in het cluster op en u kunt dit gebruiken om eroverheen te lopen. Het verschil tussen beide is dat de eerste instructie alle niet-MySQL-hosts omvat (ook de CMON-host), de tweede alle MySQL-hosts en de laatste alleen de Galera-hosts. Dus als uw Galera-cluster MySQL-asynchrone leesslaves heeft aangesloten, worden die hosts niet opgenomen.

Afgezien daarvan gedragen deze objecten zich allemaal hetzelfde en hebben ze de mogelijkheid om hun variabelen, status en query's tegen hen te lezen.

Advisor-knoppen

Nu we een nieuwe adviseur hebben gemaakt, zijn er zes nieuwe knoppen beschikbaar voor deze adviseur:

Opslaan slaat uw laatste wijzigingen op in de adviseur (opgeslagen in de CMON-database), Verplaatsen zal de adviseur naar een nieuw pad verplaatsen en Verwijderen zal de adviseur uiteraard verwijderen.

Interessanter is de tweede rij knoppen. Door het compileren van de adviseur wordt de code van de adviseur samengesteld. Als de code goed compileert, ziet u dit bericht in de Berichten dialoog onder de code van de adviseur:

Als de compilatie echter is mislukt, zal de compiler u een hint geven waar deze is mislukt:

In dit geval geeft de compiler aan dat er een syntaxisfout is gevonden op regel 24.

De compileren en uitvoeren knop compileert niet alleen het script, maar voert het ook uit en de uitvoer ervan wordt weergegeven in het dialoogvenster Berichten, Grafiek of Raw. Als we het tabelcachescript compileren en uitvoeren vanuit de auto_tuners, krijgen we een uitvoer die er ongeveer zo uitziet:

Laatste knop is het schema knop. Hiermee kunt u uw adviseurs in- of uitplannen en er tags aan toevoegen. We zullen dit aan het einde van dit bericht bespreken wanneer we onze eigen adviseur hebben gemaakt en deze willen plannen.

Mijn eerste adviseur

Nu we de basis van de ClusterControl Developer Studio hebben behandeld, kunnen we nu eindelijk beginnen met het maken van een nieuwe adviseur. Als voorbeeld zullen we een adviseur maken om naar de tijdelijke tafelverhouding te kijken. Maak als volgt een nieuwe adviseur aan:

De theorie achter de adviseur die we gaan maken is eenvoudig:we zullen het aantal tijdelijke tabellen dat op schijf is gemaakt vergelijken met het totale aantal tijdelijke tabellen dat is gemaakt:

tmp_disk_table_ratio = Created_tmp_disk_tables / (Created_tmp_tables + Created_tmp_disk_tables) * 100;

Eerst moeten we enkele basisprincipes instellen in de kop van het script, zoals de drempels en de waarschuwings- en ok-berichten. Alle wijzigingen en toevoegingen worden hieronder toegepast:

var WARNING_THRESHOLD=20;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive." ;

We stellen de drempel hier op 20 procent, wat al als behoorlijk slecht wordt beschouwd. Maar meer over dat onderwerp zodra we onze adviseur hebben afgerond.

Vervolgens moeten we deze statusvariabelen uit MySQL halen. Voordat we conclusies trekken en een "SHOW GLOBAL STATUS LIKE 'Created_tmp_%'"-query uitvoeren, is er al een functie om de statusvariabele van een MySQL-instantie op te halen, zoals we hierboven beschreven, waar deze functie zich bevindt in common/mysql_helper. js:

statusVar = readStatusVariable(<host>, <statusvariablename>);

We kunnen deze functie in onze adviseur gebruiken om de Created_tmp_disk_tables en Created_tmp_tables op te halen.

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var tmp_tables = readStatusVariable(host, ‘Created_tmp_tables’);
        var tmp_disk_tables = readStatusVariable(host, ‘Created_tmp_disk_tables’);

En nu kunnen we de tijdelijke schijftabellenverhouding berekenen:

        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;

En alert als deze verhouding groter is dan de drempel die we in het begin hebben ingesteld:

        if(checkPrecond(host))
        {
           if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive");
               msg = ADVICE_WARNING;
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }

Het is belangrijk om de Advice hier aan de variabele msg toe te wijzen, omdat deze later met de functie setAdvice() aan het adviesobject wordt toegevoegd. Het volledige script voor de volledigheid:

#include "common/mysql_helper.js"

/**
 * Checks the percentage of max ever used connections 
 * 
 */ 
var WARNING_THRESHOLD=20;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive.";

function main()
{
    var hosts     = cluster::mySqlNodes();
    var advisorMap = {};

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var tmp_tables = readStatusVariable(host, 'Created_tmp_tables');
        var tmp_disk_tables = readStatusVariable(host, 'Created_tmp_disk_tables');
        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
        
        if(!connected)
            continue;
        if(checkPrecond(host))
        {
           if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive");
               msg = ADVICE_WARNING;
               advice.setSeverity(0);
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }
        else
        {
            msg = "Not enough data to calculate";
            advice.setJustification("there is not enough load on the server or the uptime is too little.");
            advice.setSeverity(0);
        }
        advice.setHost(host);
        advice.setTitle(TITLE);
        advice.setAdvice(msg);
        advisorMap[idx]= advice;
    }
    return advisorMap;
}

Nu kun je spelen met de drempel van 20, proberen deze te verlagen naar bijvoorbeeld 1 of 2 en dan zie je waarschijnlijk wel hoe deze adviseur je daadwerkelijk advies gaat geven.

Zoals je kunt zien, kun je met een eenvoudig script twee variabelen met elkaar vergelijken en rapporteren/advies geven op basis van hun uitkomst. Maar is dat alles? Er zijn nog een aantal dingen die we kunnen verbeteren!

Verbeteringen aan mijn eerste adviseur

Het eerste dat we kunnen verbeteren, is dat deze adviseur niet veel zin heeft. Wat de statistiek feitelijk weerspiegelt, is het totale aantal tijdelijke tabellen op schijf sinds de laatste FLUSH STATUS of het opstarten van MySQL. Wat er niet staat, is tegen welk tarief het creëert in feite tijdelijke tabellen op schijf. Dus we kunnen de Created_tmp_disk_tables converteren naar een snelheid met behulp van de uptime van de host:

    var tmp_disk_table_rate = tmp_disk_tables / uptime;

Dit zou ons het aantal tijdelijke tabellen per seconde moeten geven en gecombineerd met de tmp_disk_table_ratio, zal dit ons een nauwkeuriger beeld geven van de dingen. Nogmaals, zodra we de drempel van twee tijdelijke tabellen per seconde hebben bereikt, willen we niet meteen een waarschuwing/advies sturen.

Een ander ding dat we kunnen verbeteren is om de readStatusVariable(, ) functie uit de common/mysql_helper.js bibliotheek niet te gebruiken. Deze functie voert elke keer dat we een statusvariabele lezen een query uit naar de MySQL-host, terwijl CMON de meeste ervan al elke seconde ophaalt en we toch geen realtime status nodig hebben. Het is niet zo dat twee of drie zoekopdrachten de hosts in het cluster doden, maar als veel van deze adviseurs op een vergelijkbare manier worden uitgevoerd, kan dit enorm veel extra zoekopdrachten opleveren.

In dit geval kunnen we dit optimaliseren door de statusvariabelen in een map op te halen met de functie host.sqlInfo() en alles in één keer op te halen als een map. Deze functie bevat de belangrijkste informatie van de host, maar niet alles. De variabele uptime die we nodig hebben voor de snelheid is bijvoorbeeld niet beschikbaar in de host.sqlInfo()-kaart en moet worden opgehaald met de functie readStatusVariable(, ) .

Zo ziet onze adviseur er nu uit, met de wijzigingen/toevoegingen vetgedrukt:

#include "common/mysql_helper.js"

/**
 * Checks the percentage of max ever used connections 
 * 
 */ 
var RATIO_WARNING_THRESHOLD=20;
var RATE_WARNING_THRESHOLD=2;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk and current rate is more than 2 temporary tables per second. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive.";

function main()
{
    var hosts     = cluster::mySqlNodes();
    var advisorMap = {};

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var hostStatus = host.sqlInfo();
        var tmp_tables = hostStatus['CREATED_TMP_TABLES'];
        var tmp_disk_tables = hostStatus['CREATED_TMP_DISK_TABLES'];
        var uptime = readStatusVariable(host, 'uptime');
        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
        var tmp_disk_table_rate = tmp_disk_tables / uptime;
        
        if(!connected)
            continue;
        if(checkPrecond(host))
        {
           if(tmp_disk_table_rate > RATE_WARNING_THRESHOLD && tmp_disk_table_ratio > RATIO_WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive: " + tmp_disk_table_rate + " tables per second and overall ratio of " + tmp_disk_table_ratio);
               msg = ADVICE_WARNING;
               advice.setSeverity(0);
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }
        else
        {
            msg = "Not enough data to calculate";
            advice.setJustification("there is not enough load on the server or the uptime is too little.");
            advice.setSeverity(0);
        }
        advice.setHost(host);
        advice.setTitle(TITLE);
        advice.setAdvice(msg);
        advisorMap[idx]= advice;
    }
    return advisorMap;
}

Mijn eerste adviseur plannen

Nadat we deze nieuwe adviseur hebben opgeslagen, gecompileerd en uitgevoerd, kunnen we deze adviseur nu inplannen. Aangezien we geen overmatige werkdruk hebben, zullen we deze adviseur waarschijnlijk eenmaal per dag uitvoeren.

De basisplanningsmodus is vergelijkbaar met Cron, die elke minuut, 5 minuten, uur, dag, maand vooraf heeft ingesteld en dit is precies wat we nodig hebben en het is heel eenvoudig om de planning te beheren. Als u dit wijzigt in geavanceerd, worden de andere grijze invoervelden ontgrendeld. Deze invoervelden werken precies hetzelfde als een crontab, dus je kunt zelfs plannen voor een bepaalde dag, dag van de maand of zelfs instellen op weekdagen.

Na deze blog zullen we een checker maken voor SELinux of veiligheidscontroles voor Spectre en Meltdown als nodes worden beïnvloed. Blijf op de hoogte!


  1. NoSQL-gegevensstreaming met MongoDB en Kafka

  2. PyMongo-transactiefout:transactienummers zijn alleen toegestaan ​​op een replicasetlid of mongo's

  3. Mangoest:diepe populatie (bevolken een bevolkt veld)

  4. log alle vragen die mangoest in de applicatie vuurt