hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

Redis Performance Probleme messen und analysieren

Um Latenz Probleme bei Redis zu analysieren, kann man das eingebaute Latency Tool von redis-cli benutzen, mit dem um 100 Requests pro Sekunde auf den Redis gepingt werden und man die Antwortszeit analysieren kann.

Konsolen Bsp:

Im Intervall von i=10 Sekunden auf localhost getestet

redis-cli --latency-history -i 10 -h 127.0.0.1 -p 6379

Output:

min: 0, max: 10, avg: 0.89 (906 samples) -- 10.01 seconds range
min: 0, max: 32, avg: 1.44 (862 samples) -- 10.00 seconds range
min: 0, max: 6, avg: 0.50 (939 samples) -- 10.00 seconds range
min: 0, max: 7, avg: 0.47 (941 samples) -- 10.01 seconds range
min: 0, max: 12, avg: 0.47 (942 samples) -- 10.00 seconds range
min: 0, max: 137, avg: 2.70 (779 samples) -- 10.01 seconds range
min: 0, max: 119, avg: 5.92 (626 samples) -- 10.06 seconds range
min: 0, max: 2389, avg: 7.31 (572 samples) -- 10.00 seconds range
min: 0, max: 14, avg: 0.64 (926 samples) -- 10.00 seconds range
min: 0, max: 9, avg: 0.50 (938 samples) -- 10.01 seconds range
min: 0, max: 16, avg: 0.47 (941 samples) -- 10.01 seconds range
min: 0, max: 21, avg: 0.56 (933 samples) -- 10.01 seconds range
min: 0, max: 23, avg: 0.56 (933 samples) -- 10.01 seconds range
min: 0, max: 150, avg: 1.95 (827 samples) -- 10.01 seconds range
min: 0, max: 131, avg: 4.22 (696 samples) -- 10.01 seconds range
min: 0, max: 131, avg: 7.06 (581 samples) -- 10.01 seconds range
min: 0, max: 4136, avg: 10.33 (488 samples) -- 10.01 seconds range
min: 0, max: 17, avg: 1.15 (886 samples) -- 10.02 seconds range
min: 0, max: 18, avg: 0.88 (906 samples) -- 10.01 seconds range
min: 0, max: 11, avg: 0.61 (928 samples) -- 10.00 seconds range
min: 0, max: 12, avg: 0.55 (936 samples) -- 10.01 seconds range
min: 0, max: 9, avg: 0.51 (937 samples) -- 10.01 seconds range

Hier kann man gut sehen, dass die Probleme mit einem Abstand von 60 Sekunden  auftreten. Dies lag in dem Fall daran, dass Redis alle 60s sich selber auf die Festplatte persistiert hat. Die entsprechende Option in den redis.conf lautete:

save 60 1000

und mit der Option

save ""

kann das persistieren auf der Festplatte ausgeschaltet werden.

 

Aber auch die Option

appendonly yes

musste auf “no” gesetzt werden, weil es dadurch auch auf zu viele Schreibzugriffe kam.

hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

Bitcoins senden testen im TestNet

Um die Zahlung mit Bitcoins zu testen ohne zahlungspflichtige Transaktionen auszulösen, muss man sich einen Wallet besorgen, bei dem man auch Test-Bitcoins (TestNet Bitcoins) senden kan:

https://copay.io/

Dort kann man sich ein Wallet einrichten in der Testwährung und erhält dann eine Bitcoin-Adresse aus dem TestNet, die alle mit “m”, z.B. mqfc7CVvhSD2eGVwkHS8s8Wc1FyZz8Z8xD

Auf dieses Konto kann man sich dann Bitcoins aufladen lassen auf der Webseite:

http://tpfaucet.appspot.com/

Danach kann man testen Zhalungen zu empfangen und zu senden und das Ergebnis auf der TestNet Blockchain verfolgen:

http://tbtc.blockr.io/

hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

PHP PDO Connection Timeout für Datenbank setzen und bestimmen

Normalerweise soll man das Datenbank Connection Timeout in PHP auslesen können mittels:

$pdo = new PDO('mysql:host=localhost;port=80;dbname=xxx', 'xxx', 'xxxx');
$pdo->getAttribute(PDO::ATTR_TIMEOUT);

Allerdings gibt das bei meiner alten PDO Version die Fehlermeldung:

SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute

Also habe ich ein Testscript geschrieben, mit dem man das Timeout provozieren kann (das Messen der Zeit ist nicht enthalten, wäre nett, wenn jemand das posten könnte):

$pdo = new PDO('mysql:host=localhost;port=80;dbname=xxx', 'xxx', 'xxxx');

Damit wird das Timeout ausgelöst.

Um das Timeout zu verlängern, kann man den Parameter PDO::ATTR_TIMEOUT setzen:

$pdo = new PDO('mysql:host=localhost;port=80;dbname=xxx', 'xxx', 'xxxx', array(
   PDO::ATTR_TIMEOUT => 5
));
hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

Bash Script um Konsolen Befehle auf mehreren Servern auszuführen

Wenn man einen Cluster von Severn administrieren muss, hilft es sehr, wenn man Befehler “in einem Rutsch” auf allen Mitgliedern des Clusters ausführen kann mit Hilfe eines einzigen Konsolen Befehls.

Wenn man z.B. den Befehl: apt-get update ausführen will auf 3 Servern, kann man folgendes Script benutzen (Dateiname ist “each” und auf dem Master abzulegen):

#!/bin/bash
echo -e "\nServer1:"
ssh serverName1$*
echo -e "\nnServer2:"
ssh serverName2$*
echo -e "\nnServer3:"
ssh serverName3$*

Der Aufruf erfolgt folgender Maßen auf der Konsole:

each "apt-get update"

Das Skript verbindet sich dann per SSH auf die Server und führt auf jedem den Befehl apt-get update aus und zeigt das Ergebnis der Operation auf der Konsole an. Vorrausetzung ist, dass die Server ohne Passwort Zugriff aufeinander haben, was in einem Cluster der Fall sein sollte. Der Befehl sollte vom Master des Clusters aus ausgeführt werden.

hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...
hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

History für MySQL Tabelle anlegen

Wenn man loggen will, wer wann und welche Änderungen an einer Tabelle “tabelle1″ gemacht hat, sollte man sich eine Tabelle namens “tabelle1_history” und automatisch per MySQL Trigger auf Update und Delete Ereignisse reagieren:

Hinweis: __XYZ__ Platzhalter sind zu ersetzen

Trigger auf Update Aktionen

CREATE DEFINER=`__USER__`@`%` TRIGGER `__DB__`.`__TRIGGER_NAME_DEL__` BEFORE DELETE ON `__DB__`.`__TABLE__` FOR EACH ROW BEGIN
    insert into
        __DB__.__TABLE_HISTORY__
        (
        dataset_id,
        my_data1
        my_data2
        created_on
        created_by
        )

    VALUES (
        OLD.id,
        OLD.my_data1
        OLD.my_data2
        OLD.created_on,
        OLD.created_by
  );

Trigger auf Delete Aktionen

CREATE DEFINER=`__USER__`@`%` TRIGGER `__DB__`.`__TRIGGER_NAME_UPDATE__` BEFORE UPDATE ON `__DB__`.`__TABLE__` FOR EACH ROW BEGIN
        insert into
        __DB__.__TABLE_HISTORY__
        (
        dataset_id,
        my_data1
        my_data2
        created_on
        created_by
        )

    VALUES (
        OLD.id,
        OLD.my_data1
        OLD.my_data2
        OLD.created_on,
        OLD.created_by
  );
hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...
hard mistakes - please write a commentsome mistakesokgoodvery good 5,00 of 500 (1 Users)
Loading ... Loading ...

PHP How to debug Segmentation Faults

Um Segementation Faults, die gerne in PHP7 zur Zeit auftreten zu bestimmen und zu analysieren, kann man folgender Weise vorgehen

1. Angabe des Speicherortes für die Coredumps

echo '/tmp/coredump_%e_%p' > /proc/sys/kernel/core_pattern

2. aktivieren der Coredumps in PHP-FPM

in der Datei: php-fpm.conf:

rlimit_core = unlimited     ; vorher: 0

3. PHP FPM restarten

service php-fpm restart

4. Analysieren der Coredumps mit gdb weiterlesen…

hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

SSH Verbindung mit PHP

Um eine SSH Verbindung mit PHP zu erstellen, gibt es mehrere Möglichkeiten:

Die saubere Lösung: Verbinden mit PHP-SSH2

Dazu muss die das Package php-ssh2 installiert werden, siehe php.net.

    $connection = ssh2_connect($host, $port);
    if(ssh2_auth_password($connection, $user, $password)){
        $stream = ssh2_exec($connection, $command);
        stream_set_blocking($stream, false);
        $stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
        $result = stream_get_contents($stream_out);
    }

Quick and dirty: Verbinden mit exec()

Einfach über die Console des Betriebsystems (sshpass sollte installiert werden, damit das Passwort mitangegeben werden kann).

$command = 'sshpass -p "'
    . $password
    . '" ssh -p '.$port.' '
    . $user. '@'. $host. ' "'
    . $sshCommand.'" ';
$result = exec($command);

Fingerprint umgehen bei wechselnden Ports

$command = 'sshpass -p "'
    . $password
    . '" ssh -p '.$port.' -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '    
    . $user. '@'. $host. ' "'
    . $sshCommand.'" ';
$result = exec($command);

In dem Beispiel wird mittels der Parameter

-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

die Fingerprint-Validierung umgangen, was man im Livebetrieb nicht machen sollten, bzw. man sollte sich den Fingerprint vorher auf der Console der Servers besorgen und dann benötigt man diese Parameter nicht.

 

hard mistakes - please write a commentsome mistakesokgoodvery good
Loading ... Loading ...

MySQL Update Deadlock InnoDB

Ein kniffeliges Problem ist letztens aufgetreten bei einer partitionierten MySQL Datenbank. Es kam immer wieder bei hoher Last zu Deadlock Meldungen seitens MySQL. Immer waren 2 Queries davon betroffen, die dieselbe Form hatten:

--Query1:
UPDATE myTable SET createdOn='2016-05-23 16:08:29', foo='y' WHERE id=1
--Query2:
UPDATE myTable SET createdOn='2016-05-23 16:08:29', foo='x' WHERE id=2

Im MySQL Error Log war ein solcher Eintrag zu finden:

mysql tables in use 1, locked 1
LOCK WAIT 106 lock struct(s), heap size 8400, 53 row lock(s)

Tip: Mit der Systemvariablen innodb_print_all_deadlocks (ab MySQL 5.5) kann man Deadlocks in InnoDB in das MySQL Error Log loggen und besser debuggen.

Eigentlich sollte es bei den beiden Queires nicht zu einem Deadlock kommen, da beide nur jeweils ein Row-Level Lock auf ihrer jeweilige Zeile haben sollten.

Dies ist auch der Fall, wenn es einen Index auf der Spalte id gibt. In diesem Fall allerdings war durch die Partitionierung der Primary (Unique) Index auf  2 Spalten gelegt worden (kombinierten Index): id und createdOn.

Dadurch, dass der Index auf beiden Soalten gelegt worden ist, kam es zu den dem Dealocks. Die Lösung war, das createdOn aus dem Update Statement zu entfernen, weil es an der Stelle auch keinen Sinn gemacht hat.