« mysql » Feed

97c7d57c23893194b0fa56035df6a5ce

Réplication MySQL en Master/Master avec partage de charge

2010-10-21 11:29

Write comment

Dans cet article nous allons essayer de mettre en place une solution qui assure la redondance d'une base de données MySQL et qui permet de partager la charge entre deux nœuds.
Pour assurer la redondance des données nous allons avoir recours à la réplication native de MySQL.
En ce qui concerne le partage de charge, nous allons utiliser MySQL Proxy bien qu'il soit encore à sa version 0.8 Alpha.

Redondance des données:

Dans cette section, nous allons configurer une réplication entre deux Maîtres MySQL, identifiés par DB-1 et DB-2, sachant que dans cette configuration, chaque Maitre sera en même temps l'esclave de l'autre.
Ce schéma est plus expressif:



Le grand avantage de cette architecture est d'avoir deux bases de données sur lesquelles on peut écrire en parallèle sans se soucier de la synchronisation, la réplication se charge de synchroniser vers DB-2 ce qu'on écrit sur DB-1, et vice versa.
C'est d'ailleurs pourquoi on va utiliser MySQL Proxy qui se placera comme partageur de charge entre ces deux bases de données.

On va commencer par mettre en place la réplication à double master:

NB: Toutes les requêtes SQL seront exécutés avec le compte root.

DB-1:

Ajouter ce qui suit à la section [mysqld] du fichier my.cnf et redémarrer mysqld:
 # primary master server id
server-id=1
auto_increment_offset=1
# total number of master servers
auto_increment_increment=2
# local slave replication options
log-bin=master1-bin
log-slave-updates
# remote master replication options
master-host=slave2.ip
master-port=3306
master-user=slave2
master-password=slave2
master-connect-retry=10 
Cette configuration indique à DB-1 d'accepter la réplication depuis Slave2.

DB-2:

Ajouter ce qui suit à la section [mysqld] du fichier my.cnf et redémarrer mysqld:
 # secondary master server id
server-id=2
auto_increment_offset=2
# total number of master servers
auto_increment_increment=2
# local slave replication options
log-bin=master2-bin
log-slave-updates
# remote master replication options
master-host=slave1.ip
master-port=3306
master-user=slave1
master-password=slave1
master-connect-retry=10 
Cette configuration indique à DB-2 d'accepter la réplication depuis Slave2.

Vous l'aurez certainement remarqué, auto_increment_offset et auto_increment_increment sont les clés du bon fonctionnement d'une réplication à double maîtres, car dans ce type de réplication et lors de l'écriture simultanée sur les deux maîtres, on aura facilement des collisions au niveau des clés auto incrémentées (auto_increment) menant à l'échec la réplication.
Prenons l'exemple de cette requête SQL
 mysql> INSERT INTO personne (id, name) VALUES (null, 'Mahmoud');  
Sachant que la colonne ID est une clé primaire auto incrémentée, à son exécution sur DB-1, la colonne ID aura la valeur '1'.
Et si on exécute une autre requête sur DB-2 comme suit
 mysql> INSERT INTO personne (id, name) VALUES (null, 'Fourat');  
La colonne ID sera incrémentée et aura la valeur '1', ce qui provoquera un conflit dans la réplication car le la deuxième ligne insérée sur DB-2 ne pourra jamais synchronisée sur DB-2 puisque la colonne ID est une clé primaire et donc unique.
Pour remédier à ce problème il faut appliquer configurer auto_increment_offset et auto_increment_increment en tenant compte de cette règle:

Read more…

6c4a91744a9f857f00ddd8802edb7465

Partitioning MySQL database with high load solutions

2010-11-19 00:35

Write comment

We need to test if MySQL can be reliable with huge data sets, talking of a daily waterfall of about 30 million INSERTs and a few daily analityc big SELECTs too.
So what's the deal ? which database engine ? which platform ? which architecture ? ... and is data secured ? accessible ?
Before choosing MySQL 5.1, i turned around these three databases:

  • Oracle :
    Known as the 'most reliable' database engine in the world, personally i don't believe in that, and i didn't choose it for its cost (Especially that :) ).
  • PostgreSQL :
    A good database engine, it succeeded where older than 5.0 versions of MySQL failed, but now, both engines are mature enough and i'm switching between them on every new projects depending on the specific needs of each project architectures.
    Switching between database engines should be a simple task when the application deploys an abstraction layer on the database.
    So why not PostgreSQL for this project ?
    1. PostgreSQL (the latest stable version to this day) still lacks on partitioning and provide very basic features compared to what MySQL do.
    2. As i know, PostgreSQL has no 'enterprise' version and no paid support, with mission critical projects, we cant rely on the community respondness to resolve issues, we need enterprise-level SLA.
  • MySQL 5.1
    Refering to the new features list of the 5.1 version of MySQL, i felt in love with it.
    Good partitioning (and sub-partitioning), better replication engine .. and the 'enterprise' version is making us comfortable with critical-mission applications.
As for scalability, making a database respond in less than 1 second when stressed with up to 2000 INSERT/sec throughput (with TRIGGER) does not rely on System sizing and Database engine only, these things wont scale if the design is poorly done.

Let's dive into the blue:
We have a sell reporting analytic application, we have about 20 million sells per day, each selling action has a Seller and a Buyer as long as the date and the amount of the bill.
The informations are provided in flat text files, so we use Talend ETL to load the data to the database.
On the output side, we need to get a fast access to these informations:
  • (1) Best sellers of each day having total amount of sells more than a defined limit. (Using the sum of the billing amounts of the day)
  • (2) Occasionally fetch selling details of a Seller for a specific period.
I've deployed two tables, the first is for delivering best sellers/buyers informations (1), the second is for the selling details (2).
Here's the first one:

CREATE TABLE `transaction` (
`seller` int(11) DEFAULT NULL,
`buyer` int(11) DEFAULT NULL,
`amount` decimal(5,2) DEFAULT 0,
`sell_date` date DEFAULT NULL,
`sell_time` time DEFAULT NULL,
PRIMARY KEY(`seller`, `buyer`, `sell_date`, `time`)
) ENGINE=InnoDB
PARTITION BY RANGE ( MONTH(`sell_date`))
SUBPARTITION BY HASH ( `seller` div 1000000)
SUBPARTITIONS 10
(
PARTITION p1 VALUES LESS THAN (1) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (2) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (3) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (4) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p6 VALUES LESS THAN (6) ENGINE = InnoDB,
PARTITION p7 VALUES LESS THAN (7) ENGINE = InnoDB,
PARTITION p8 VALUES LESS THAN (8) ENGINE = InnoDB,
PARTITION p9 VALUES LESS THAN (9) ENGINE = InnoDB,
PARTITION p10 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p11 VALUES LESS THAN (11) ENGINE = InnoDB,
PARTITION p12 VALUES LESS THAN MAXVALUE ENGINE = InnoDB
);

This table will contain the sell transactions, I've made partitioning by seller and month of the transaction in the way to facilitate queries for selling details for a specific seller and period: (2).

Here's the second one (dedicated to queries fetching best sellers of each day (1)):

Read more…

 Nbre d'élements: 2/
2