sql >> Database teknologi >  >> NoSQL >> MongoDB

Skriv din første rådgiver

Har du nogensinde spekuleret på, hvad der udløser rådet i ClusterControl om, at din disk er ved at blive fyldt op? Eller rådet om at oprette primære nøgler på InnoDB-tabeller, hvis de ikke eksisterer? Disse rådgivere er miniscripts skrevet i ClusterControl Domain Specific Language (DSL), som er et Javascript-lignende sprog. Disse scripts kan skrives, kompileres, gemmes, udføres og planlægges i ClusterControl. Det er, hvad ClusterControl Developer Studio-blogserien vil handle om.

I dag vil vi dække det grundlæggende i Developer Studio og vise dig, hvordan du opretter din allerførste rådgiver, hvor vi vælger to statusvariabler og giver råd om deres resultat.

Rådgiverne

Rådgivere er miniscripts, der udføres af ClusterControl, enten on-demand eller efter en tidsplan. De kan være alt fra simple konfigurationsråd, advarsler om tærskler eller mere komplekse regler for forudsigelser eller klyngeomfattende automatiseringsopgaver baseret på status for dine servere eller databaser. Generelt udfører rådgivere mere detaljerede analyser og producerer mere omfattende anbefalinger end advarsler.

Rådgiverne gemmes i ClusterControl-databasen, og du kan tilføje nye eller ændre/ændre eksisterende rådgivere. Vi har også et rådgiver Github-lager, hvor du kan dele dine rådgivere med os og andre ClusterControl-brugere.

Sproget der bruges til rådgiverne er det såkaldte ClusterControl DSL og er et letforståeligt sprog. Sprogets semantik kan bedst sammenlignes med Javascript med et par forskelle, hvor de vigtigste forskelle er:

  • Semikoloner er obligatoriske
  • Forskellige numeriske datatyper såsom heltal og lange lange heltal uden fortegn.
  • Arrays er todimensionelle og enkeltdimensionelle arrays er lister.

Du kan finde den fulde liste over forskelle i ClusterControl DSL-referencen.

Udviklerstudiegrænsefladen

Developer Studio-grænsefladen kan findes under Cluster> Administrer> Developer Studio. Dette åbner en grænseflade som denne:

Rådgivere

Advisors-knappen vil generere en oversigt over alle rådgivere med deres output siden sidste gang, de kørte:

Du kan også se tidsplanen for rådgiveren i crontab-format og dato/klokkeslæt siden sidste opdatering. Nogle rådgivere er planlagt til kun at køre én gang om dagen, så deres råd afspejler muligvis ikke længere virkeligheden, for eksempel hvis du allerede har løst det problem, du blev advaret om. Du kan manuelt køre rådgiveren igen ved at vælge rådgiveren og køre den. Gå til afsnittet "kompiler og kør" for at læse, hvordan du gør dette.

Importrådgivere

Knappen Importer giver dig mulighed for at importere en tarball med nye rådgivere i dem. Tarballen skal oprettes i forhold til rådgivernes hovedsti, så hvis du ønsker at uploade en ny version af MySQL query cache size scriptet (s9s/mysql/query_cache/qc_size.js), bliver du nødt til at starte tarballen fra s9s-biblioteket.

Eksportrådgivere

Du kan eksportere rådgiverne eller en del af dem ved at vælge en node i træet og trykke på knappen Eksporter. Dette vil skabe en tarball med filerne i den fulde sti til den præsenterede struktur. Antag, at vi ønsker at lave en sikkerhedskopi af s9s/mysql-rådgiverne, før vi foretager en ændring, vælger vi blot s9s/mysql-noden i træet og trykker på Eksporter:

Bemærk:sørg for, at s9s-biblioteket er til stede i /home/myuser/.

Dette vil skabe en tarball kaldet /home/myuser/s9s/mysql.tar.gz med en intern mappestruktur s9s/mysql/*

Oprettelse af en ny rådgiver

Da vi har dækket eksport og import, kan vi nu begynde at eksperimentere. Så lad os oprette en ny rådgiver! Klik på knappen Ny for at få følgende dialog:

I denne dialog kan du oprette din nye rådgiver med enten en tom fil eller på forhånd udfylde den med den Galera- eller MySQL-specifikke skabelon. Begge skabeloner vil tilføje de nødvendige indbefatter (common/mysql_helper.js) og det grundlæggende for at hente Galera- eller MySQL-noder og sløjfe over dem.

Oprettelse af en ny rådgiver med Galera-skabelonen ser sådan ud:

#include "common/mysql_helper.js"

Her kan du se, at mysql_helper.js bliver inkluderet for at give grundlaget for at forbinde og forespørge MySQL-noder.

Denne fil indeholder funktioner, som du kan aktivere, hvis det er nødvendigt, som f.eks. readVariable(,), som giver dig mulighed for at få den globale variableværdi eller kalde readStatusVariable(,), som også giver dig mulighed for for at få de globale statusvariabler i MySQL. Denne fil kan findes i træet som vist nedenfor:

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

Advarselstærsklen er i øjeblikket sat til 0, hvilket betyder, at hvis den målte tærskel er større end advarselstærsklen, skal rådgiveren advare brugeren. Bemærk at den variable tærskel ikke er sat/brugt i skabelonen endnu, da det er en kickstart for din egen rådgiver.

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

Udsagn ovenfor henter værterne i klyngen, og du kan bruge dette til at sløjfe over dem. Forskellen mellem dem er, at den første sætning inkluderer alle ikke-MySQL-værter (også CMON-værten), den anden alle MySQL-værter og den sidste kun Galera-værterne. Så hvis din Galera-klynge har MySQL asynkrone læseslaver tilknyttet, vil disse værter ikke blive inkluderet.

Bortset fra det vil disse objekter alle opføre sig ens og have evnen til at læse deres variabler, status og forespørgsel mod dem.

Advisor-knapper

Nu hvor vi har oprettet en ny rådgiver, er der seks nye knapper tilgængelige for denne rådgiver:

Gem gemmer dine seneste ændringer i rådgiveren (gemt i CMON-databasen), Flyt vil flytte rådgiveren til en ny sti og Fjern vil naturligvis fjerne rådgiveren.

Mere interessant er den anden række af knapper. Kompilering af rådgiveren vil kompilere rådgiverens kode. Hvis koden kompilerer fint, vil du se denne besked i Beskeder dialog under rådgiverens kode:

Mens kompileringen mislykkedes, vil compileren give dig et tip, hvor den mislykkedes:

I dette tilfælde angiver compileren, at der blev fundet en syntaksfejl på linje 24.

Kompiler og kør knappen vil ikke kun kompilere scriptet, men også udføre det, og dets output vil blive vist i meddelelser, graf eller rå dialog. Hvis vi kompilerer og kører tabelcache-scriptet fra auto_tunerne, får vi output svarende til dette:

Sidste knap er tidsplanen knap. Dette giver dig mulighed for at planlægge (eller annullere) dine rådgivere og tilføje tags til det. Vi vil dække dette i slutningen af ​​dette indlæg, når vi har oprettet vores helt egen rådgiver og vil planlægge det.

Min første rådgiver

Nu hvor vi har dækket det grundlæggende i ClusterControl Developer Studio, kan vi nu endelig begynde at oprette en ny rådgiver. Som et eksempel vil vi oprette en rådgiver til at se på det midlertidige tabelforhold. Opret en ny rådgiver som følger:

Teorien bag den rådgiver, vi skal lave, er enkel:vi vil sammenligne antallet af midlertidige tabeller, der er oprettet på disken, med det samlede antal midlertidige tabeller, der er oprettet:

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

Først skal vi indstille nogle grundlæggende ting i hovedet af scriptet, såsom tærsklerne og advarslen og ok beskeder. Alle ændringer og tilføjelser anvendes nedenfor:

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." ;

Vi sætter tærsklen her til 20 procent, hvilket anses for at være ret dårligt allerede. Men mere om det emne, når vi har færdiggjort vores rådgiver.

Dernæst skal vi hente disse statusvariabler fra MySQL. Før vi hopper til konklusioner og udfører en "VIS GLOBAL STATUS LIKE 'Created_tmp_%'"-forespørgsel, er der allerede en funktion til at hente statusvariablen for en MySQL-instans, som det vi beskrev ovenfor, hvor denne funktion er placeret i common/mysql_helper. js:

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

Vi kan bruge denne funktion i vores rådgiver til at hente Create_tmp_disk_tables og Created_tmp_tables.

    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’);

Og nu kan vi beregne det midlertidige disk-tabellforhold:

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

Og advare, hvis dette forhold er større end den tærskel, vi satte i begyndelsen:

        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;
           }
        }

Det er vigtigt at tildele Advice til msg-variablen her, da denne vil blive tilføjet senere i rådgivningsobjektet med setAdvice()-funktionen. Det fulde script for fuldstændighed:

#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 kan du lege med tærsklen på 20, prøve at sænke den til f.eks. 1 eller 2, og så kan du sikkert se, hvordan denne rådgiver faktisk vil give dig råd om sagen.

Som du kan se, kan du med et simpelt script kontrollere to variable mod hinanden og rapportere/rådgive baseret på deres resultat. Men er det alt? Der er stadig et par ting, vi kan forbedre!

Forbedringer af min første rådgiver

Det første, vi kan forbedre, er, at denne rådgiver ikke giver meget mening. Hvad metrikken faktisk afspejler, er det samlede antal midlertidige tabeller på disken siden sidste FLUSH STATUS eller opstart af MySQL. Hvad der ikke står, er til hvilken hastighed det opretter faktisk midlertidige tabeller på disken. Så vi kan konvertere Create_tmp_disk_tables til en hastighed ved hjælp af værtens oppetid:

    var tmp_disk_table_rate = tmp_disk_tables / uptime;

Dette skulle give os antallet af midlertidige tabeller pr. sekund, og kombineret med tmp_disk_table_ratio vil dette give os et mere præcist overblik over tingene. Igen, når vi når tærsklen på to midlertidige borde i sekundet, ønsker vi ikke straks at sende en advarsel/rådgivning.

En anden ting, vi kan forbedre, er ikke at bruge funktionen readStatusVariable(, ) fra common/mysql_helper.js-biblioteket. Denne funktion udfører en forespørgsel til MySQL-værten, hver gang vi læser en statusvariabel, mens CMON allerede henter de fleste af dem hvert sekund, og vi har alligevel ikke brug for en realtidsstatus. Det er ikke sådan, at to eller tre forespørgsler vil dræbe værterne i klyngen, men hvis mange af disse rådgivere køres på en lignende måde, kan dette skabe masser af ekstra forespørgsler.

I dette tilfælde kan vi optimere dette ved at hente statusvariablerne i et kort ved at bruge funktionen host.sqlInfo() og hente alt på én gang som et kort. Denne funktion indeholder de vigtigste oplysninger om værten, men den indeholder ikke alle. For eksempel er den variable oppetid, som vi har brug for til hastigheden, ikke tilgængelig i host.sqlInfo()-kortet og skal hentes med funktionen readStatusVariable(, ).

Sådan kommer vores rådgiver til at se ud nu, med ændringerne/tilføjelserne markeret med fed:

#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;
}

Planlægning af min første rådgiver

Efter at vi har gemt denne nye rådgiver, kompileret den og kørt, kan vi nu planlægge denne rådgiver. Da vi ikke har en overdreven arbejdsbyrde, vil vi sandsynligvis køre denne rådgiver én gang om dagen.

Basisplanlægningstilstanden ligner Cron, som har hvert minut, 5 minutter, time, dag, måned forudindstillet, og det er præcis, hvad vi har brug for, og det er meget nemt at styre planlægningen. Ændring af dette til avanceret vil låse de andre nedtonede inputfelter op. Disse inputfelter fungerer nøjagtigt det samme som en crontab, så du kan endda planlægge en bestemt dag, dag i måneden eller endda indstille den til hverdage.

Efter denne blog vil vi oprette en checker til SELinux eller sikkerhedstjek for Spectre og Meltdown, hvis noder er påvirket. Hold dig opdateret!


  1. Få kun et specificeret felt i MongoDB med C#

  2. Hvad skal du vide, når du begynder at arbejde med MongoDB i produktionen - ti tips

  3. Find den samlede tid brugt af en bruger i mongoDB

  4. redis + gevent - Dårlig ydeevne - hvad gør jeg forkert?