Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Inne aspekty Memcached & MySQL

Inne aspekty Memcached & MySQL

Presentation abstract:

Memcached and MySQL probably needs no introduction to anyone. They are working great standalone but together they can solve most of the performance issues related to the database layer. It should be noted that both projects complement each other perfectly well in other situations, far from typical caching of data.

In the first part of the presentation we will see HandlerSocket which introduces simplified and directe access to database table's storage engine, which can greatly improve performance of primary key seeks even up to several hundred thousand reads per second. HandlerSocket inspired the memcached API introduced in MySQL 5.6, that we will dicuss a bit more.

The second part will be focused on using MySQL to transfer data between memcached clusters in different locations. When scaling applications with different server room locations there is often a need to place in each of them local, consistent copy of data cache to provide fast and easy access to key data. On the example of Facebook architecture we will look at the problems of fault resistant method to solve this problem, which in addition can also be used in smaller projects, such as session data redundancy.

Abstrakt prezentacji:

Memcached i MySQL to rozwiązania, których chyba nie trzeba przedstawiać nikomu. Idealnie działają solo, a w typowym połączeniu potrafią skutecznie rozwiązać większość problemów wydajnościowych związanych z warstwą bazy danych. Warto jednak zwrócić uwagę, iż oba projekty świetnie uzupełniają się także w innych zastosowaniach, dalekich od typowego cache’owania danych.

W pierwszej części prezentacji poznamy m.in. rozwiązanie HandlerSocket, które wprowadza do bazy danych MySQL uproszczony i bezpośredni dostęp do storage-engine’u tabeli, co w konsekwencji pozwala osiągnąć ilość odczytów względem klucza głównego na poziomie kilkuset tysięcy operacji na sekundę. HandlerSocket stał się pierwowzorem wprowadzonego w MySQL 5.6 memcached API, którego możliwościom poświęcimy znacznie więcej uwagi.

Druga część skoncentrowana będzie na wykorzystaniu MySQL do przenoszenia danych pomiędzy klastrami memcached zlokalizowanych w odległych centrach danych.W przypadku skalowania aplikacji na poziomie osobnych serwerowni często zachodzi potrzeba umieszczenia w każdej z nich lokalnych, spójnych kopii danych cache, aby zapewnić szybki i łatwy dostęp do kluczowych danych. Na przykładzie zastosowanej przez Facebook architektury zapoznamy się pełni odporną na problemy metodą rozwiązania tego problemu, którą dodatkowo można zastosować także w mniejszych projektach, np. do redundancji danych sesyjnych.

Mariusz Gil

August 06, 2012
Tweet

More Decks by Mariusz Gil

Other Decks in Programming

Transcript

  1. function pobierz_dane(int userid) { /* Najpierw próba pobrania danych z

    cache */ data = memcached_fetch("userrow:" + userid); if (!data) { /* Nie znaleziono wymaganych danych => pobranie danych z bazy danych, */ data = db_select("SELECT * FROM users WHERE userid = ?", userid); /* następnie po pobraniu danych, przechowywanie ich w cache. */ memcached_add("userrow:" + userid, data); } return data; } function aktualizuj_dane(int userid, string dbUpdateString) { /* Najpierw aktualizacja bazy danych */ result = db_execute(dbUpdateString); if (result) { /* Aktualizacja bazy danych powiodła się => pobranie danych przechowywanych w bazie danych, */ data = db_select("SELECT * FROM users WHERE userid = ?", userid); /* następnie wprowadzenie danych do pamięci podręcznej. */ memcached_set("userrow:" + userid, data); /* ostatnia linia powinna wyglądać: //data = createDataFromDBString(dbUpdateString); */ } } prosty przykład poniedziałek, 6 sierpnia 2012
  2. California data center Virginia data center MySQL master memcached MySQL

    slave memcached replikacja poniedziałek, 6 sierpnia 2012
  3. California data center Virginia data center MySQL master memcached MySQL

    slave memcached aktualizacja profilu aktualizacja danych replikacja usuniecie danych usuniecie danych poniedziałek, 6 sierpnia 2012
  4. replikacja MySQL w czasie ponizej 1 sek okresowo nawet powyzej

    20 sek ` . . poniedziałek, 6 sierpnia 2012
  5. California data center Virginia data center MySQL master memcached MySQL

    slave memcached aktualizacja profilu aktualizacja danych replikacja rozszerzona o dane memcached usuniecie danych usuniecie danych aktualizacja danych poniedziałek, 6 sierpnia 2012
  6. MySQL master memcached MySQL slave memcached aktualizacja danych replikacja rozszerzona

    o dane memcached usuniecie danych danych aktualizacja danych query : statement END_OF_INPUT {} ; statement : alter | analyze | backup | call | insert | replace | select | update ... ; query : statement mc_dirty END_OF_INPUT {} ; mc_dirty : {} | MEMCACHE_DIRTY mc_key_list ; mc_key_list : mc_key_list ‘,’ text_string { Lex->mc_key_list.push_back($3); } | text_string { Lex->mc_key_list.push_back($1); } ; mysql_execute_command() poniedziałek, 6 sierpnia 2012
  7. MySQL master tabela BlackHole binlog MySQL slave watek replikacji tabela

    BlackHole trigger memcached MySQL slave watek replikacji tabela BlackHole trigger memcached MySQL slave watek replikacji tabela BlackHole trigger memcached SET key foo 1 } zapis przez aplikacje lub memcached API GET key http://golanzakai.blogspot.com/2008/11/memcached-replication-and-namespaces.html , poniedziałek, 6 sierpnia 2012
  8. aplikacje duzej skali nie stosuja JOIN-ów a odczyt jest głównie

    wzgledem PK nawet kosztem redundancji danych . , , poniedziałek, 6 sierpnia 2012
  9. mysql> CREATE TABLE t ( id int(11) NOT NULL, col

    varchar(20) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; dostep do tych samych danych $ telnet 127.0.0.1 9999 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. P 1 test t PRIMARY id col 0 1 1 + 2 1 test value 0 1 mysql> SELECT * FROM t; +----+------------+ | id | col | +----+------------+ | 1 | test value | +----+------------+ , poniedziałek, 6 sierpnia 2012
  10. MySQL API dla złozonych zapytan HandlerSocket dla zapytan szybkich lub

    index scan wątek workera wątek na połączenie Akceptacja protokolu Parsowanie SQL Optymalizacja SQL Otwarcie tabel Query Plan Query Cache Dostep do danych Zamkniecie tabel Zwrócenie wyników Akceptacja protokołu Dostep do danych Zwrócenie wyników Storage Engine 3306 9998 9999 InnoDB MyISAM ... . ` ` , poniedziałek, 6 sierpnia 2012
  11. dostep do tych samych danych telnet localhost 11211 Trying ::1...

    Connected to localhost. Escape character is '^]'. set mykey 0 0 14 abcd|1234|WXYZ STORED get mykey VALUE mykey 0 14 abcd|1234|WXYZ END mysql> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM kvstore WHERE `key`="mykey"; +-------+-------+-------+------+---------+------+------+ | key | value | flags | cas | expires | val2 | val3 | +-------+-------+-------+------+---------+------+------+ | mykey | abcd | 0 | 1 | 0 | 1234 | WXYZ | +-------+-------+-------+------+---------+------+------+ 1 row in set (0.00 sec) , poniedziałek, 6 sierpnia 2012
  12. InnoDB Storage Engine InnoDB API Handler API MySQL Server Memcached

    Plugin proces mysqld proces php/java/ruby Aplikacja protokół SQL protokół memcached innodb_memcache local cache poniedziałek, 6 sierpnia 2012
  13. definicja mapowania InnoDB / memcached polityki wykonań operacji SET/GET/DELETE/FLUSH opcje

    konfiguracyjne np. separator wartości poniedziałek, 6 sierpnia 2012
  14. Memcached Listener proces memcached proces php/java/ruby protokół memcached Memcached Driver

    dla NDB NDB API C++ Aplikacja siec lokalna NDB data NDB data NDB data NDB data NDB data NDB Cluster poniedziałek, 6 sierpnia 2012
  15. proces memcached proces php/java/ruby Aplikacja NDB data NDB data NDB

    data NDB data NDB data NDB Cluster GET key_1 key_2 NDB API GET key_1 key_3 ndb-only cache poniedziałek, 6 sierpnia 2012
  16. dostep do tych samych danych mysql> CREATE DATABASE clusterdb; mysql>

    USE clusterdb; mysql> CREATE TABLE towns_tab ( town VARCHAR(30) NOT NULL PRIMARY KEY, zip VARCHAR(10), population INT, county VARCHAR(10) ) ENGINE=NDB; mysql> INSERT INTO towns_tab VALUES ('Marlow', 'SL7', 14004, 'Berkshire'); mysql> USE ndbmemcache; mysql> INSERT INTO containers VALUES ('towns_cnt', 'clusterdb', 'towns_tab', 'town', 'zip', 0, NULL, NULL, NULL, NULL); mysql> INSERT INTO containers VALUES ('pop_cnt', 'clusterdb', 'towns_tab', 'town', 'population', 0, NULL, NULL, NULL, NULL); mysql> SELECT * FROM containers; +------------+-------------+------------------+-------------+---------------- | name | db_schema | db_table | key_columns | value_columns +------------+-------------+------------------+-------------+---------------- | towns_cnt | clusterdb | towns_tab | town | zip | pop_cnt | clusterdb | towns_tab | town | population +------------+-------------+------------------+-------------+---------------- mysql> INSERT INTO key_prefixes VALUES (1, 'twn_pr:', 0, 'ndb-only', 'towns_cnt'); mysql> INSERT INTO key_prefixes VALUES (1, 'pop_pr:', 0, 'ndb-only', 'pop_cnt'); mysql> SELECT * FROM key_prefixes; +----------------+------------+------------+---------------+------------+ | server_role_id | key_prefix | cluster_id | policy | container | +----------------+------------+------------+---------------+------------+ | 1 | pop_pr: | 0 | ndb-only | pop_cnt | | 1 | twn_pr: | 0 | ndb-only | towns_cnt | +----------------+------------+------------+---------------+------------+ , poniedziałek, 6 sierpnia 2012
  17. dostep do tych samych danych memcached -E /usr/local/mysql/lib/ndb_engine.so -e "connectstring=localhost:1186;role=db-only"

    -vv -c 20 Contacting primary management server (localhost:1186) ... Connected to "localhost:1186" as node id 51. Retrieved 2 key prefixes for server role "db-only". The default behavior is that: GET uses NDB only SET uses NDB only DELETE uses NDB only. The 2 explicitly defined key prefixes are "pop_pr:" (towns_tab), "twn_pr:" (towns_tab) telnet localhost 11211 get twn_pr:Marlow VALUE twn_pr:Marlow 0 3 SL7 END set twn_pr:Maidenhead 0 0 3 SL6 STORED set pop_pr:Maidenhead 0 0 5 42827 STORED mysql> SELECT * FROM clusterdb.towns_tab; +------------+------+------------+-----------+ | town | zip | population | county | +------------+------+------------+-----------+ | Maidenhead | SL6 | 42827 | NULL | | Marlow | SL7 | 14004 | Berkshire | +------------+------+------------+-----------+ , poniedziałek, 6 sierpnia 2012