SlideShare a Scribd company logo
1 of 62
Download to read offline
SaaS con Symfony2 
un caso *molto* concreto di applicazione multitenant
@ftassi 
Francesco Tassi 
@matteomoretti85 
Matteo Moretti
Nuvola e i suoi 50GB
Nuvola e i suoi 50GB 
• Difficoltà di manutenzione (backup/ripristino) 
• Difficoltà di evoluzione (alter dello schema) 
• Impossibile replicare il sistema (debug)
Applicazioni multi 
tenant
Applicazioni multi 
tenant 
“Multi-tenant si riferisce ad una architettura 
software in cui una singola istanza del suddetto 
software gira su un server ed è utilizzata da più di 
una client organization (tenant)”. 
– wikipedia
Sharding
Sharding 
A database shard is a horizontal partition of data 
in a database. Each individual partition is referred 
to as a shard or database shard. Each shard is 
held on a separate database server instance, to 
spread load. 
– wikipedia
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus
Sharding 
user_id username 
1 idiopathic 
2 bouffant 
3 skedaddle 
user_id username 
4 tweezers 
5 igloo 
6 foibles 
7 oocephalus 
Shard 1 
Shard 2
Vantaggi 
• Suddivide anche il carico di scrittura 
• Indici più piccoli 
• distribuzione dei dati migliore
Svantaggi 
• Difficile o impossibile effettuare query su shard 
differenti 
• Consistenza dei dati 
• Complessità extra
Supporto nativo 
http://en.wikipedia.org/wiki/ 
Shard_(database_architecture)#Support_for_sh 
ards
Sharding con Doctrine
Sharding con Doctrine 
Starting with 2.3 Doctrine DBAL contains some 
functionality to simplify the development of 
horizontally sharded applications. 
! 
In this first release it contains a ShardManager 
interface. This interface allows to programatically 
select a shard to send queries to. 
- http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
Sharding con Doctrine 
At the moment there are no functionalities yet to 
dynamically pick a shard based on ID, query or 
database row yet 
- http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
ShardManager Interface 
$shardManager = new PoolingShardManager($conn); 
! 
$currentCustomerId = 1234; 
$shardManager->selectShard($currentCustomerId); 
// all queries after this call hit the shard 
// where customer with id 1234 is on. 
! 
$shardManager->selectGlobal(); 
// the global database is selected.
https://www.flickr.com/photos/reallyboring/3234624436 
Il Piano
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Il Piano 
Strategia di frazionamento 
Strategia di selezione del DB 
Switch della connessione 
Tool di gestione per N databases
Strategia di 
frazionamento
KEEP CALM 
AND 
SPLIT YOUR DATA
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
2 2 bouffant 
3 1 skedaddle 
4 1 tweezers 
5 2 igloo 
6 1 foibles 
7 1 oocephalus
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
2 2 bouffant 
3 1 skedaddle 
4 1 tweezers 
5 2 igloo 
6 1 foibles 
7 1 oocephalus
Strategia di frazionamento 
user_id istituto_id! username 
1 1 idiopathic 
3 1 skedaddle 
4 1 tweezers 
6 1 foibles 
7 1 oocephalus 
user_id istituto_id! username 
2 2 bouffant 
5 2 igloo 
Shard 1 
Shard 2
Strategia di selezione 
del DB
Sottodominio?
Sottodominio
Chiedilo all’utente
Chiedilo all’utente 
• Login tramite database unico (default) ! 
• Selezione manuale dell’istituto 
• Switch della connessione 
• Sincronizzazione dei dati duplicati
Una connessione “default” 
doctrine: 
dbal: 
default_connection: default 
connections: 
default: 
driver: "%database_driver%" 
host: "%database_host%" 
port: "%database_port%" 
dbname: "%database_name%" 
user: "%database_user%" 
password: "%database_password%" 
charset: UTF8
500 Shards 
shards: 
mc12345678: 
id: 1 
host: '%database_host%' 
user: '%database_user%' 
password: '%database_password%' 
dbname: nuvolamc12345678 
charset: UTF8 
mcps015006: 
id: 2 
host: '%database_host%' 
user: '%database_user%' 
password: '%database_password%' 
dbname: mcps015006 
charset: UTF8
UUID 
user_id istituto_id! username uuid 
1 1 idiopathic 
e5f0b536- 
c4cd-47c4- 
a810- 
2 2 bouffant 
ea5d2eb4-851c 
-462d-a25e- 
1756bece 
3 1 skedaddle 
a5889369-61d8 
-4b3c-b93f-cd4a3d449c46 
4 1 tweezers 
cd5759ae-7a7e 
-42d1- 
b4cf-0cd0701b 
5 2 igloo 
64976e7a-54d2 
-4230-a8ef-d624dc320cee 
6 1 foibles 
202528c0-7028 
-4a6f-9c0b-e97c6544693c 
7 1 oocephalus 
30bd250c-0a9c 
-4cf2- 
a54c-020804d1
Sincronizzazione 
(onFlush, prePersist) 
$this 
->eventDispatcher 
->dispatch( 
MultiDbSyncEntityEvent::SYNC_UTENTE, 
new MultiDbSyncEntityEvent($utente) 
);
Sincronizzazione 
public function onSyncUtente(MultiDbSyncEntityEvent 
$event) 
{ 
$user = $event->getEntity(); 
$shard = $this->getShardToSync($user); 
/** @var $connection DoctrineDBALConnection */ 
$connection = $this->doctrine->getConnection($this- 
>getConnectionNameFromShard($shard)); 
$this->syncUser($user, $connection); 
}
500 Connessioni 
nuvolamc12345678: 
driver: '%database_driver%' 
host: '%database_host%' 
port: '%database_port%' 
dbname: nuvolamc12345678 
user: '%database_user%' 
password: '%database_password%' 
charset: UTF8 
nuvolamcps015006: 
driver: '%database_driver%' 
host: '%database_host%' 
port: '%database_port%' 
dbname: nuvolamcps015006 
user: '%database_user%' 
password: '%database_password%' 
charset: UTF8
Switch della 
connessione
Switch della connessione 
private function selectDbForIstituto( 
Istituto $istituto, 
SessionInterface $session 
) 
{ 
$shardManager = $this->get('shard_manager'); 
$shardManager->selectShard($istituto); 
! 
$session->set('shard', $istituto->getShardId()); 
}
Switch della connessione 
public function onKernelRequest(GetResponseEvent $event) 
{ 
if (!$event->isMasterRequest()) { 
return; 
} 
! 
$this->shardManager->selectShard( 
$this->session->get(‘shard') 
); 
}
https://www.flickr.com/photos/jdhancock/8671399450/ 
Gestire 500 DB 
Help needed
Configurare gli shards 
protected function configure() 
{ 
$this->setName('nuvola:shard:add-config') 
->setDescription('Aggiunge la configurazione 
necessaria ad uno shard') 
->addOption('host', null, InputOption::VALUE_OPTIONAL, 
'L'host della connessione al db') 
->addOption('codiceMeccanografico', null, 
InputOption::VALUE_OPTIONAL, 'Codice meccanografico per lo 
shard'); 
}
Configurare gli shards 
protected function configure() 
{ 
$this->setName('nuvola:shard:create-config') 
->setDescription('Crea il file di configurazione per gli 
shards') 
->addOption( 
'append', 
null, 
InputOption::VALUE_NONE, 
'Se impostato a false cancella la configurazione attuale, 
altrimenit la aggiunge. Default a true' 
) 
//CUT 
}
Ad ognuno il suo shard 
public function onConsoleCommand(ConsoleCommandEvent $event) 
{ 
$shardManager = new SafeShardManager($connection); 
$istituto = $input->getParameterOption(['--istituto', '-i']); 
! 
if ('global' === $istituto) { 
$shardManager->selectGlobal(); 
} else { 
$shardManager->selectShard($istituto); 
} 
! 
}
Ciclare gli shards 
class ListShardsCommand extends AbstractShardCommand 
{ 
protected function configure() 
{ 
$this->setName('nuvola:shard:list-shards') 
->setDescription('Restituisce l'elenco degli shard configurati') 
->addOption( 
'letteraInizioIntervallo', 
null, 
InputOption::VALUE_OPTIONAL, 
'Lettera di inizio intervallo per lo shard da esportare (estremo 
compreso)' 
) 
->addOption( 
'letteraFineIntervallo', 
null, 
InputOption::VALUE_OPTIONAL, 
'Lettera di fine intervallo per lo shard da esportare (estremo compreso)' 
); 
} 
}
Ciclare gli shards 
app/console nu:sha:li | while read 
shard; do app/console doctrine:mig:mig - 
i $shard -n;done;
Parallelizzare FTW 
class MigrateCommand extends AbstractParallelCommand 
{ 
protected function execute(InputInterface $input, OutputInterface 
$output) 
{ 
/** @var GearmanClient $gearman */ 
$gearman = $this->getContainer()->get('gearman'); 
//[CUT] 
foreach ($shards as $shard) { 
$job = 'NuvolaMultiDbBundleWorkerShardWorker~migrate' . 
$shard['queue']; 
$gearman->addTask($job, $shard['shard']); 
} 
! 
$gearman->runTasks(); 
} 
}
Parallelizzare FTW 
protected function doMigrate(GearmanJob $job) 
{ 
$shard = $job->workload(); 
$command = sprintf( 
'app/console doctrine:migrations:migrate -n -i %s --env=%s', 
$shard, 
$this->env 
); 
! 
$process = $this->runProcess($job, $command); 
! 
if (!$process->isSuccessful()) { 
$this->sendErrorsToJob($job, $process, $command, 'Errore migrando ' . $shard); 
return; 
} 
! 
$success = [sprintf('Migrazione per %s completata', $shard)]; 
$job->sendComplete(serialize($success)); 
! 
return; 
}
Parallelizzare FTW 
app/console gearman:job:execute 
NuvolaMultiDbBundleWorkerShardWorker~mig 
rate0 -n —env=prod
Conclusioni
Fa al caso tuo?
Si, lo rifarei
Domande?
https://joind.in/12212
Hiring! 
http://www.ideato.it/offerta-cercasi-sviluppatore- 
php/
Thanks

More Related Content

What's hot

Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
MongoDB
 
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
Laboratorio Di  Basi Di  Dati 08  Il  Web Server  ApacheLaboratorio Di  Basi Di  Dati 08  Il  Web Server  Apache
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
guestbe916c
 
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
Laboratorio Di  Basi Di  Dati 09  Il Linguaggio  P H PLaboratorio Di  Basi Di  Dati 09  Il Linguaggio  P H P
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
guestbe916c
 

What's hot (18)

Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
Creating Highly-Available MongoDB Microservices with Docker Containers and Ku...
 
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
Laboratorio Di  Basi Di  Dati 08  Il  Web Server  ApacheLaboratorio Di  Basi Di  Dati 08  Il  Web Server  Apache
Laboratorio Di Basi Di Dati 08 Il Web Server Apache
 
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
Laboratorio Di  Basi Di  Dati 09  Il Linguaggio  P H PLaboratorio Di  Basi Di  Dati 09  Il Linguaggio  P H P
Laboratorio Di Basi Di Dati 09 Il Linguaggio P H P
 
Backup di un sito Joomla! - Procedure semplici, veloci e sicure
Backup di un sito Joomla! - Procedure semplici, veloci e sicureBackup di un sito Joomla! - Procedure semplici, veloci e sicure
Backup di un sito Joomla! - Procedure semplici, veloci e sicure
 
Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)
Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)
Back to Basics 4: Introduzione al partizionamento orizzontale (sharding)
 
Drupal Day 2011 - Node.js e Drupal
Drupal Day 2011 - Node.js e DrupalDrupal Day 2011 - Node.js e Drupal
Drupal Day 2011 - Node.js e Drupal
 
Cloud storage in azienda: perche` Riak ci e` piaciuto
Cloud storage in azienda: perche` Riak ci e` piaciutoCloud storage in azienda: perche` Riak ci e` piaciuto
Cloud storage in azienda: perche` Riak ci e` piaciuto
 
Seminario team working - 21-1-2015
Seminario team working - 21-1-2015Seminario team working - 21-1-2015
Seminario team working - 21-1-2015
 
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
 
Pgtraining bdr
Pgtraining bdrPgtraining bdr
Pgtraining bdr
 
Elasticsearch a quick introduction
Elasticsearch a quick introductionElasticsearch a quick introduction
Elasticsearch a quick introduction
 
JBoss Data Grid Tech Lab
JBoss Data Grid Tech LabJBoss Data Grid Tech Lab
JBoss Data Grid Tech Lab
 
Programmazione web libera dai framework
Programmazione web libera dai frameworkProgrammazione web libera dai framework
Programmazione web libera dai framework
 
SQL Saturday 871 - Sardegna 2019 - SQL Server DR on Azure
SQL Saturday 871 - Sardegna 2019 - SQL Server DR on AzureSQL Saturday 871 - Sardegna 2019 - SQL Server DR on Azure
SQL Saturday 871 - Sardegna 2019 - SQL Server DR on Azure
 
Data grid
Data gridData grid
Data grid
 
High Performance Web Apps con PHP e Symfony 2
High Performance Web Apps con PHP  e Symfony 2High Performance Web Apps con PHP  e Symfony 2
High Performance Web Apps con PHP e Symfony 2
 
October 2009 - JBoss Cloud
October 2009 - JBoss CloudOctober 2009 - JBoss Cloud
October 2009 - JBoss Cloud
 
Async navigation with a lightweight ES6 framework
Async navigation with a lightweight ES6 frameworkAsync navigation with a lightweight ES6 framework
Async navigation with a lightweight ES6 framework
 

Viewers also liked

พีระมิด
พีระมิดพีระมิด
พีระมิด
duangduand
 
ใบงาน
ใบงานใบงาน
ใบงาน
duangduand
 
ทรงกระบอก
ทรงกระบอกทรงกระบอก
ทรงกระบอก
duangduand
 
Lets see the reality around us
Lets see the reality around usLets see the reality around us
Lets see the reality around us
Tishi Bali
 
Converted by pdf suite
Converted by pdf suiteConverted by pdf suite
Converted by pdf suite
duangduand
 
Prolog (present)
Prolog (present) Prolog (present)
Prolog (present)
Melody Joey
 

Viewers also liked (20)

Scaling symfony apps
Scaling symfony appsScaling symfony apps
Scaling symfony apps
 
Nuvola: a tale of migration to AWS
Nuvola: a tale of migration to AWSNuvola: a tale of migration to AWS
Nuvola: a tale of migration to AWS
 
La scuola entra nella nuvola- Matteo Moretti
La scuola entra nella nuvola- Matteo MorettiLa scuola entra nella nuvola- Matteo Moretti
La scuola entra nella nuvola- Matteo Moretti
 
Symfony как микрофреймворк
Symfony как микрофреймворкSymfony как микрофреймворк
Symfony как микрофреймворк
 
Multi kernelowa aplikacja w oparciu o Symfony 3 i microkernele
Multi kernelowa aplikacja w oparciu o Symfony 3 i microkerneleMulti kernelowa aplikacja w oparciu o Symfony 3 i microkernele
Multi kernelowa aplikacja w oparciu o Symfony 3 i microkernele
 
Research 2
Research 2Research 2
Research 2
 
Demo: How to make air refreshener ? (Powder form & Spray form)
Demo: How to make air refreshener ?(Powder form & Spray form)Demo: How to make air refreshener ?(Powder form & Spray form)
Demo: How to make air refreshener ? (Powder form & Spray form)
 
Black Box Testing
Black Box TestingBlack Box Testing
Black Box Testing
 
พีระมิด
พีระมิดพีระมิด
พีระมิด
 
Gross u11a3
Gross u11a3Gross u11a3
Gross u11a3
 
ใบงาน
ใบงานใบงาน
ใบงาน
 
ทรงกระบอก
ทรงกระบอกทรงกระบอก
ทรงกระบอก
 
Diapositivas
DiapositivasDiapositivas
Diapositivas
 
Презентация слайды2
Презентация слайды2Презентация слайды2
Презентация слайды2
 
Lets see the reality around us
Lets see the reality around usLets see the reality around us
Lets see the reality around us
 
Converted by pdf suite
Converted by pdf suiteConverted by pdf suite
Converted by pdf suite
 
Physics
PhysicsPhysics
Physics
 
Excel trick
Excel trickExcel trick
Excel trick
 
Prolog (present)
Prolog (present) Prolog (present)
Prolog (present)
 
Mot 3033
Mot 3033Mot 3033
Mot 3033
 

Similar to SaaS con Symfony2

Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
Tommaso Torti
 

Similar to SaaS con Symfony2 (20)

SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenantSaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
 
Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1
 
Php mysql3
Php mysql3Php mysql3
Php mysql3
 
MongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDBMongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDB
 
Sviluppo web dall'antichità all'avanguardia e ritorno
Sviluppo web  dall'antichità all'avanguardia e ritornoSviluppo web  dall'antichità all'avanguardia e ritorno
Sviluppo web dall'antichità all'avanguardia e ritorno
 
EE Incremental Store
EE Incremental StoreEE Incremental Store
EE Incremental Store
 
Mantenere una distribuzione Drupal attraverso test coverage: Paddle case study
Mantenere una distribuzione Drupal attraverso test coverage: Paddle case studyMantenere una distribuzione Drupal attraverso test coverage: Paddle case study
Mantenere una distribuzione Drupal attraverso test coverage: Paddle case study
 
Come Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagineCome Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagine
 
Levate l'ancora! Rotte senza problemi con ZF2
Levate l'ancora! Rotte senza problemi con ZF2Levate l'ancora! Rotte senza problemi con ZF2
Levate l'ancora! Rotte senza problemi con ZF2
 
Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
 
Programmazione e gestione della sicurezza: Verbale elettronico
Programmazione e gestione della sicurezza: Verbale elettronicoProgrammazione e gestione della sicurezza: Verbale elettronico
Programmazione e gestione della sicurezza: Verbale elettronico
 
Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.
Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.
Sicurezza Php (giugno 2010) Stefano Bianchini presso Ce.Se.N.A.
 
SQL Server & GDPR
SQL Server & GDPRSQL Server & GDPR
SQL Server & GDPR
 
September 2010 - Gatein
September 2010 - GateinSeptember 2010 - Gatein
September 2010 - Gatein
 
Idp, passo dopo passo!
Idp, passo dopo passo!Idp, passo dopo passo!
Idp, passo dopo passo!
 
DDAY2014 - Performance in Drupal 8
DDAY2014 - Performance in Drupal 8DDAY2014 - Performance in Drupal 8
DDAY2014 - Performance in Drupal 8
 
(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...
(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...
(in)Sicurezza nella PA - Gianluca Varisco, Cybersecurity del Team per la Tras...
 
Perl Template Toolkit
Perl Template ToolkitPerl Template Toolkit
Perl Template Toolkit
 
Spring, IBatis e Transazioni Aop Nel Jug Avis Web
Spring, IBatis e Transazioni Aop Nel Jug Avis WebSpring, IBatis e Transazioni Aop Nel Jug Avis Web
Spring, IBatis e Transazioni Aop Nel Jug Avis Web
 
PostgrSQL 9.3&9.4 - DjangoVillage
PostgrSQL 9.3&9.4 - DjangoVillagePostgrSQL 9.3&9.4 - DjangoVillage
PostgrSQL 9.3&9.4 - DjangoVillage
 

SaaS con Symfony2

  • 1. SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
  • 2. @ftassi Francesco Tassi @matteomoretti85 Matteo Moretti
  • 3.
  • 4. Nuvola e i suoi 50GB
  • 5. Nuvola e i suoi 50GB • Difficoltà di manutenzione (backup/ripristino) • Difficoltà di evoluzione (alter dello schema) • Impossibile replicare il sistema (debug)
  • 7. Applicazioni multi tenant “Multi-tenant si riferisce ad una architettura software in cui una singola istanza del suddetto software gira su un server ed è utilizzata da più di una client organization (tenant)”. – wikipedia
  • 9. Sharding A database shard is a horizontal partition of data in a database. Each individual partition is referred to as a shard or database shard. Each shard is held on a separate database server instance, to spread load. – wikipedia
  • 10. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle 4 tweezers 5 igloo 6 foibles 7 oocephalus
  • 11. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle 4 tweezers 5 igloo 6 foibles 7 oocephalus
  • 12. Sharding user_id username 1 idiopathic 2 bouffant 3 skedaddle user_id username 4 tweezers 5 igloo 6 foibles 7 oocephalus Shard 1 Shard 2
  • 13. Vantaggi • Suddivide anche il carico di scrittura • Indici più piccoli • distribuzione dei dati migliore
  • 14. Svantaggi • Difficile o impossibile effettuare query su shard differenti • Consistenza dei dati • Complessità extra
  • 15. Supporto nativo http://en.wikipedia.org/wiki/ Shard_(database_architecture)#Support_for_sh ards
  • 17. Sharding con Doctrine Starting with 2.3 Doctrine DBAL contains some functionality to simplify the development of horizontally sharded applications. ! In this first release it contains a ShardManager interface. This interface allows to programatically select a shard to send queries to. - http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
  • 18. Sharding con Doctrine At the moment there are no functionalities yet to dynamically pick a shard based on ID, query or database row yet - http://doctrine-dbal.readthedocs.org/en/latest/reference/sharding.html
  • 19. ShardManager Interface $shardManager = new PoolingShardManager($conn); ! $currentCustomerId = 1234; $shardManager->selectShard($currentCustomerId); // all queries after this call hit the shard // where customer with id 1234 is on. ! $shardManager->selectGlobal(); // the global database is selected.
  • 20.
  • 22. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 23. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 24. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 25. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 26. Il Piano Strategia di frazionamento Strategia di selezione del DB Switch della connessione Tool di gestione per N databases
  • 27.
  • 29. KEEP CALM AND SPLIT YOUR DATA
  • 30. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 2 2 bouffant 3 1 skedaddle 4 1 tweezers 5 2 igloo 6 1 foibles 7 1 oocephalus
  • 31. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 2 2 bouffant 3 1 skedaddle 4 1 tweezers 5 2 igloo 6 1 foibles 7 1 oocephalus
  • 32. Strategia di frazionamento user_id istituto_id! username 1 1 idiopathic 3 1 skedaddle 4 1 tweezers 6 1 foibles 7 1 oocephalus user_id istituto_id! username 2 2 bouffant 5 2 igloo Shard 1 Shard 2
  • 37. Chiedilo all’utente • Login tramite database unico (default) ! • Selezione manuale dell’istituto • Switch della connessione • Sincronizzazione dei dati duplicati
  • 38. Una connessione “default” doctrine: dbal: default_connection: default connections: default: driver: "%database_driver%" host: "%database_host%" port: "%database_port%" dbname: "%database_name%" user: "%database_user%" password: "%database_password%" charset: UTF8
  • 39. 500 Shards shards: mc12345678: id: 1 host: '%database_host%' user: '%database_user%' password: '%database_password%' dbname: nuvolamc12345678 charset: UTF8 mcps015006: id: 2 host: '%database_host%' user: '%database_user%' password: '%database_password%' dbname: mcps015006 charset: UTF8
  • 40. UUID user_id istituto_id! username uuid 1 1 idiopathic e5f0b536- c4cd-47c4- a810- 2 2 bouffant ea5d2eb4-851c -462d-a25e- 1756bece 3 1 skedaddle a5889369-61d8 -4b3c-b93f-cd4a3d449c46 4 1 tweezers cd5759ae-7a7e -42d1- b4cf-0cd0701b 5 2 igloo 64976e7a-54d2 -4230-a8ef-d624dc320cee 6 1 foibles 202528c0-7028 -4a6f-9c0b-e97c6544693c 7 1 oocephalus 30bd250c-0a9c -4cf2- a54c-020804d1
  • 41. Sincronizzazione (onFlush, prePersist) $this ->eventDispatcher ->dispatch( MultiDbSyncEntityEvent::SYNC_UTENTE, new MultiDbSyncEntityEvent($utente) );
  • 42. Sincronizzazione public function onSyncUtente(MultiDbSyncEntityEvent $event) { $user = $event->getEntity(); $shard = $this->getShardToSync($user); /** @var $connection DoctrineDBALConnection */ $connection = $this->doctrine->getConnection($this- >getConnectionNameFromShard($shard)); $this->syncUser($user, $connection); }
  • 43. 500 Connessioni nuvolamc12345678: driver: '%database_driver%' host: '%database_host%' port: '%database_port%' dbname: nuvolamc12345678 user: '%database_user%' password: '%database_password%' charset: UTF8 nuvolamcps015006: driver: '%database_driver%' host: '%database_host%' port: '%database_port%' dbname: nuvolamcps015006 user: '%database_user%' password: '%database_password%' charset: UTF8
  • 45. Switch della connessione private function selectDbForIstituto( Istituto $istituto, SessionInterface $session ) { $shardManager = $this->get('shard_manager'); $shardManager->selectShard($istituto); ! $session->set('shard', $istituto->getShardId()); }
  • 46. Switch della connessione public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } ! $this->shardManager->selectShard( $this->session->get(‘shard') ); }
  • 48. Configurare gli shards protected function configure() { $this->setName('nuvola:shard:add-config') ->setDescription('Aggiunge la configurazione necessaria ad uno shard') ->addOption('host', null, InputOption::VALUE_OPTIONAL, 'L'host della connessione al db') ->addOption('codiceMeccanografico', null, InputOption::VALUE_OPTIONAL, 'Codice meccanografico per lo shard'); }
  • 49. Configurare gli shards protected function configure() { $this->setName('nuvola:shard:create-config') ->setDescription('Crea il file di configurazione per gli shards') ->addOption( 'append', null, InputOption::VALUE_NONE, 'Se impostato a false cancella la configurazione attuale, altrimenit la aggiunge. Default a true' ) //CUT }
  • 50. Ad ognuno il suo shard public function onConsoleCommand(ConsoleCommandEvent $event) { $shardManager = new SafeShardManager($connection); $istituto = $input->getParameterOption(['--istituto', '-i']); ! if ('global' === $istituto) { $shardManager->selectGlobal(); } else { $shardManager->selectShard($istituto); } ! }
  • 51. Ciclare gli shards class ListShardsCommand extends AbstractShardCommand { protected function configure() { $this->setName('nuvola:shard:list-shards') ->setDescription('Restituisce l'elenco degli shard configurati') ->addOption( 'letteraInizioIntervallo', null, InputOption::VALUE_OPTIONAL, 'Lettera di inizio intervallo per lo shard da esportare (estremo compreso)' ) ->addOption( 'letteraFineIntervallo', null, InputOption::VALUE_OPTIONAL, 'Lettera di fine intervallo per lo shard da esportare (estremo compreso)' ); } }
  • 52. Ciclare gli shards app/console nu:sha:li | while read shard; do app/console doctrine:mig:mig - i $shard -n;done;
  • 53. Parallelizzare FTW class MigrateCommand extends AbstractParallelCommand { protected function execute(InputInterface $input, OutputInterface $output) { /** @var GearmanClient $gearman */ $gearman = $this->getContainer()->get('gearman'); //[CUT] foreach ($shards as $shard) { $job = 'NuvolaMultiDbBundleWorkerShardWorker~migrate' . $shard['queue']; $gearman->addTask($job, $shard['shard']); } ! $gearman->runTasks(); } }
  • 54. Parallelizzare FTW protected function doMigrate(GearmanJob $job) { $shard = $job->workload(); $command = sprintf( 'app/console doctrine:migrations:migrate -n -i %s --env=%s', $shard, $this->env ); ! $process = $this->runProcess($job, $command); ! if (!$process->isSuccessful()) { $this->sendErrorsToJob($job, $process, $command, 'Errore migrando ' . $shard); return; } ! $success = [sprintf('Migrazione per %s completata', $shard)]; $job->sendComplete(serialize($success)); ! return; }
  • 55. Parallelizzare FTW app/console gearman:job:execute NuvolaMultiDbBundleWorkerShardWorker~mig rate0 -n —env=prod
  • 57. Fa al caso tuo?