<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Decrypt &#187; Sharding / Partitionnement</title>
	<atom:link href="http://decrypt.ysance.com/category/architecture/sharding/feed/" rel="self" type="application/rss+xml" />
	<link>http://decrypt.ysance.com</link>
	<description>Le site de decryptage des technologies de l&#039;informatique</description>
	<lastBuildDate>Thu, 01 Jul 2010 14:41:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Scaler une infrastructure AWS 2/2 : le modèle</title>
		<link>http://decrypt.ysance.com/2010/07/scaler-une-infrastructure-aws-2-le-modele/</link>
		<comments>http://decrypt.ysance.com/2010/07/scaler-une-infrastructure-aws-2-le-modele/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 14:41:53 +0000</pubDate>
		<dc:creator>Frédéric Faure</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Sharding / Partitionnement]]></category>
		<category><![CDATA[Amazon Web Services]]></category>
		<category><![CDATA[Casual Gaming]]></category>
		<category><![CDATA[LVM]]></category>
		<category><![CDATA[Memcached]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[RAID]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Tokyo Cabinet]]></category>
		<category><![CDATA[Tokyo Tyrant]]></category>

		<guid isPermaLink="false">http://decrypt.ysance.com/?p=1304</guid>
		<description><![CDATA[<img class="size-medium wp-image-1411 alignleft" title="Scale-Out in the Matrix" src="http://decrypt.ysance.com/wp-content/uploads/2010/06/MatrixScaleOut-300x123.png" alt="Scale-Out in the Matrix" width="204" height="82" />

Comment scaler une infrastructure <a title="Site de Amazon Web Services" href="http://aws.amazon.com/">AWS</a> (Amazon Web Services) ? Je vais décrire dans cette deuxième partie de l'article le modèle de l'architecture et les composants techniques sous-jacents à adopter afin de mettre en place une infrastructure scalable. Nous aborderons tout particulièrement le sujet de l'optimisation de l'accès aux données dans les architectures de type scale-out propices à la distribution, autant au niveau du modèle de données que des couches basses pour l'optimisation des I/O. Nous verrons également les concepts de développement à privilégier tel que le stateless dans la plus pure tradition REST. Je terminerai par quelques trucs et astuces en fin d'article. Le but est de vous permettre de constituer et d'optimiser votre infrastructure en comprenant le fonctionnement des outils proposés par Amazon pour en tirer le meilleur parti.

[...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-medium wp-image-1411 alignleft" title="Scale-Out in the Matrix" src="http://decrypt.ysance.com/wp-content/uploads/2010/06/MatrixScaleOut-300x123.png" alt="Scale-Out in the Matrix" width="204" height="82" /></p>
<p>Comment scaler une infrastructure <a title="Site de Amazon Web Services" href="http://aws.amazon.com/">AWS</a> (Amazon Web Services) ? Je vais décrire dans cette deuxième partie de l&#8217;article le modèle de l&#8217;architecture et les composants techniques sous-jacents à adopter afin de mettre en place une infrastructure scalable. Nous aborderons tout particulièrement le sujet de l&#8217;optimisation de l&#8217;accès aux données dans les architectures de type scale-out propices à la distribution, autant au niveau du modèle de données que des couches basses pour l&#8217;optimisation des I/O. Nous verrons également les concepts de développement à privilégier tel que le stateless dans la plus pure tradition REST. Je terminerai par quelques trucs et astuces en fin d&#8217;article. Le but est de vous permettre de constituer et d&#8217;optimiser votre infrastructure en comprenant le fonctionnement des outils proposés par Amazon pour en tirer le meilleur parti.</p>
<p><strong><em>Le scale-out</em></strong><br />
<img class="size-full wp-image-1424 alignright" title="Scale-Up in Ghost Buster" src="http://decrypt.ysance.com/wp-content/uploads/2010/06/GhostBusterScaleUp.jpg" alt="Scale-Up in Ghost Buster" width="116" height="170" />Le scale-out est à opposer au scale-up : ce dernier correspond à l&#8217;augmentation dynamique des ressources d&#8217;un serveur donné (ajout de RAM ou de CPU) à la volée. Ainsi l&#8217;application continue à s&#8217;exécuter sur une même machine dont le potentiel à augmenté. Le scale-out, lui, pour répondre à la montée en charge d&#8217;une application propose d&#8217;augmenter le nombre de serveurs. Au final, le potentiel global de l&#8217;infrastructure augmente aussi, mais est réparti entre plusieurs serveurs. Cela implique que l&#8217;application supportée sur le serveur ait été pensée en termes de distribution, c&#8217;est à dire qu&#8217;elle puisse s&#8217;exécuter en parallèle sur plusieurs serveurs sans que cela n&#8217;en corrompe la logique métier ou ne pose des problèmes d&#8217;accès aux ressources (qui doivent alors être disponibles via le réseau et non en local sur un serveur donné par exemple).</p>
<p>Le scale-out, c&#8217;est un peu l&#8217;agent Smith de Matrix. Pour le scale-up, pensez plutôt au gentil bibendum de Ghost Buster !</p>
<p><em><strong>Stateless</strong></em><br />
Le meilleur moyen d&#8217;obtenir une application facilement distribuable et performante est de la penser en mode stateless. C&#8217;est à dire que c&#8217;est la requête du client qui doit contenir l&#8217;ensemble des informations qui vont permettre le traitement de ladite requête côté serveur, soit via un cookie ou bien via les paramètres de l&#8217;URL. Quand cela est possible il faut privilégier cette approche à tout prix par rapport au mode statefull dans lequel la partie serveur doit maintenir un contexte pour chaque client afin de pouvoir résoudre sa requête. La conception stateless fait parti des grands concepts du REST. A ce sujet, je ne peux que vous conseiller de lire cet <a title="REST, un style d'architecture universel" href="http://www.figer.com/publications/REST.htm">excellent article sur REST</a> de Jean-Paul Figer dans lequel vous pourrez comprendre toute la simplicité et la puissance du style.</p>
<p>Si vous êtes obligés de gérer du statefull, il vous faudra utiliser un cache réseau, tel que <a title="Site de Memcached" href="http://memcached.org/">Memcached</a>, pour partager les contextes entre vos différents serveurs. N&#8217;envisagez pas la formule cache local et sticky session, car vous aurez du mal à bénéficier d&#8217;une répartition fluide au niveau de votre load balancing. N&#8217;envisagez pas non plus un cluster qui communique en multicast car le réseau Amazon ne permet pas d&#8217;en faire&#8230; Ou bien alors il faudrait que tous les serveurs communiquent en unicast avec une gateway qui s&#8217;occupe de la redistribution des communications&#8230; Vous êtes sûr que vous ne préférez pas du stateless ? ;ob</p>
<p>La mise en place d&#8217;applications stateless n&#8217;est pas arrivée avec le Cloud Computing et les AWS, en revanche ne pas penser dans ce sens, vous empêcherait de bénéficier de tout le dynamisme et la souplesse proposés par ces services.</p>
<p><em><strong>Optimisation de l&#8217;accès aux données</strong></em><br />
L&#8217;optimisation de l&#8217;accès aux données passe par 2 éléments :</p>
<ul>
<li>Le modèle de données et l&#8217;architecture logicielle que l&#8217;on retrouve  dans les architectures scalables, que l&#8217;on soit sur une infrastructure  AWS ou non.</li>
<li>La gestion des I/O que l&#8217;on peut optimiser, notamment via une utilisation approfondie des AWS.</li>
</ul>
<p><em><span style="text-decoration: underline;">Le modèle scalable</span></em><br />
Cela pourrait faire l&#8217;objet d&#8217;un article à part entière, mais correspond  à un modèle assez classique au sein des applications de type casual  gaming ou bien plus généralement liées à des applications basées sur les  graphes sociaux ou bien centrées sur une notion métier forte en particulier.</p>
<p>Pour résumer, 2 méthodes de stockage de données :</p>
<ul>
<li>Un stockage de ce que l&#8217;on peut appeler le méta-modèle, qui n&#8217;a pas  vocation à être distribué, basé sur une base relationnelle (même si  essentiellement utilisée sous forme d&#8217;accès clé-valeur) structurée,  indexée, contenant les informations générales de chaque utilisateur  (dans la cas d&#8217;une application sociale, avec les informations <em>nom</em>, <em>top score</em>, <em>gains de la veille</em>, &#8230;), essentiellement accédées en  lecture et dont il est possible d&#8217;alléger la charge via un Memcached en  frontal. Il est donc possible d&#8217;effectuer des requêtes ensemblistes de type SQL et ainsi de récupérer des informations via l&#8217;utilisation de clauses (<em>WHERE</em>). Cette base peut être un MySQL ou un PgSQL par exemple. Je vous invite à lire ce <a title="Dotdeb, MySQL et Amazon : RDS vs EC2" href="http://www.dotdeb.org/2010/05/04/mysql-on-amazon-benchmarks-rds-vs-ec2/">comparatif très intéressant</a> de Guillaume Plessis entre l&#8217;utilisation de MySQL installé sur un <a title="Site de Amazon Web Services, Rubrique EC2" href="http://aws.amazon.com/ec2/">EC2</a> et l&#8217;utilisation du service <a title="Site de Amazon Web Services, Rubrique RDS" href="http://aws.amazon.com/rds/">RDS</a> (Relational Database Service) d&#8217;Amazon. Je ne trahirai en rien le suspens en vous disant que la base de données c&#8217;est une histoire de barbus ! :o)</li>
<li>Un stockage pour les données plus volatiles (comme les données de jeu, &#8230;), avec un fort rapport  écriture/lecture, difficilement cachables, et pour lesquelles il faut  opter pour une réelle solution de stockage structurée non relationnelle  de type clé-valeur (NoSQL / Not only SQL diront certains), permettant  ainsi de distribuer facilement les données sur X serveurs. On peut citer un nombre  certain de candidats : <a title="Site de Redis" href="http://code.google.com/p/redis/">Redis</a>, <a title="Site de Tokyo Tyrant" href="http://1978th.net/tokyotyrant/">Tokyo Tyrant</a>/<a title="Site de Tokyo Cabinet" href="http://1978th.net/tokyocabinet/">Tokyo Cabinet</a>, <a title="Site de MemcacheDB" href="http://memcachedb.org/">MemcacheDB</a>, &#8230; Et également les nouveaux modèles peer to peer tels que <a title="Site de Cassandra" href="http://cassandra.apache.org/">Cassandra</a>, &#8230;</li>
</ul>
<div id="attachment_1353" class="wp-caption alignright" style="width: 291px"><img class="size-full wp-image-1353" title="Tokyo Cabinet" src="http://decrypt.ysance.com/wp-content/uploads/2010/06/TokyoCabinet.png" alt="Tokyo Cabinet" width="281" height="183" /><p class="wp-caption-text">Tokyo Cabinet</p></div>
<p>En l&#8217;occurrence, Tokyo Tyrant / Tokyo Cabinet est une solution que j&#8217;ai mise en place et qui me semble bonne. C&#8217;est un couple gérant respectivement les requêtes à partir de  serveurs distants (interface réseau) et les accès au système de  stockage. 6 APIs sont disponibles afin de stocker les données :</p>
<ol>
<li> On memory Hash,</li>
<li>On memory B+tree,</li>
<li>File Hash,</li>
<li>File B+tree,</li>
<li>Fixed-length Array,</li>
<li>Table.</li>
</ol>
<p>Chacune d’entre elles a ses propres spécificités et répond à des  besoins particuliers en termes de performances et de fonctionnalités.</p>
<p>Au niveau performances, outre ses performances naturelles, il a  l&#8217;avantage, notamment, de ne pas gérer l&#8217;authentification (standard chez les  systèmes de stockage clé-valeur, la sécurité est censée être assurée au niveau réseau pour les accès au système de stockage et au niveau applicatif pour les accès à la donnée &#8211; pour ne récupérer que ce qui vous concerne), ce qui allège le nombre d&#8217;accès (pas besoin de  requêtes d&#8217;authentification) par rapport à une base de données classique.  De plus, pas de gestion d&#8217;index lourds à reconstruire (possible  cependant sur l&#8217;API &laquo;&nbsp;Table&nbsp;&raquo; de la Tokyo Team), &#8230; Est-il nécessaire de préciser que ce  qui vous prendra du temps sur l’accès à la donnée via le réseau (entre  le serveur web ou applicatif et Tokyo Tyrant) c’est… Le réseau ! Donc  dans tous les cas, préférez l’utilisation au niveau client (API) de  « mget » (multi get), par exemple, en positionnant en paramètre le  tableau de clés que vous souhaitez récupérer, plutôt que d’effectuer N  fois un « get » à partir du client, donc N accès réseau. « mget » se  résoudra, lui, au niveau de Tokyo Tyrant.</p>
<p>Ces raisonnements appliqués sur cet outil doivent être appliqués à tout stockage de type clé-valeur.</p>
<p><span style="text-decoration: underline;"><em>La gestion des I/O</em></span><br />
Venons-en à la spécificité des AWS en termes de stockage : les <a title="Site de Amazon Web Services, Rubrique EBS" href="http://aws.amazon.com/ebs/">EBS</a> (Elastic Block Store). Les EBS sont des disques réseau optimisés en I/O, faciles à  manipuler, permettant d&#8217;assurer la durabilité des données qui ne doivent  pas être perdues lors de l&#8217;arrêt d&#8217;un EC2 (volatile). J&#8217;ai cependant  constaté de manière empirique des écarts de latence : pas énormes, mais  sur une application réellement sollicitée, il y a un ressenti.  Ce n&#8217;est pas rédhibitoire, il faut juste en tenir compte. Si le Load  Average de vos serveurs augmente, ce n&#8217;est pas forcément le CPU en  cause&#8230; Pensez I/O ! ;ob</p>
<p>Tout d&#8217;abord penser striping, donc RAID0. Pas besoin de mirroring (RAID1), la  durabilité des EBS est déjà assurée par Amazon, de manière transparente, par réplication réseau :  tirons parti de ce service et concentrons nous sur le striping. Pensez  également à répartir les écritures des différents fichiers physiques  (données, updates logs, …) sur différents disques (dans le cas d&#8217;outils  utilisant des update logs, et c&#8217;est le cas pour MySQL et Tokyo Tyrant  par exemple, pensez à bien paramétrer leur taille). C&#8217;est ce qui permet  d&#8217;avoir les meilleures optimisations. Ensuite, choisissez bien votre  système de fichier par rapport à votre outil (EXT3, XFS, …) et pensez  aux options de montage (noatime, nodiratime, &#8230;). Finalement vérifiez  bien le scheduler/ordonnanceur par défaut sur les instances EC2 que vous  démarrez : par défaut, il s&#8217;agit de l&#8217;ordonnanceur NOOP (requêtes I/O  dans une simple file FIFO). Envisagez quelque chose de plus performant  comme CFQ (Completely Fair Queuing) par exemple&#8230; Enfin je dis ça, mais cela dépend toujours de la couche logiciel au-dessus et si et comment elle gère les priorités : <a title="MySQL Performance Blog, Linux schedulers in tpcc like benchmark" href="http://www.mysqlperformanceblog.com/2009/01/30/linux-schedulers-in-tpcc-like-benchmark/">dans cet exemple</a> (qui n&#8217;est pas sur EBS) sur MySQL Performance Blog, il apparaît que les ordonnanceurs NOOP et DEADLINE peuvent être de meilleure facture pour améliorer les I/O InnoDB. Comme quoi, il faut quand même mieux tester dans son propre cas ! ;ob</p>
<div id="attachment_1177" class="wp-caption alignleft" style="width: 310px"><img class="size-medium wp-image-1177" title="Logical Volume Management" src="http://decrypt.ysance.com/wp-content/uploads/2010/06/Archi_LVM-300x280.png" alt="Logical Volume Management" width="300" height="280" /><p class="wp-caption-text">Logical Volume Management</p></div>
<p>Un autre outil que j&#8217;ai utilisé avec les EBS et qui fonctionne très  bien est LVM2 (Logical Volume Management, version 2). Je ne l&#8217;ai pas  utilisé dans le cadre d&#8217;une architecture avec un nombre élevé d&#8217;IOPS (I/O operations Per Second) et n&#8217;ai donc pas  testé les possibilités de striping (RAID0) offertes par l&#8217;outil. En revanche, je l&#8217;ai utilisé dans  le cadre d&#8217;une infrastructure nécessitant de pouvoir supporter des  augmentations conséquentes du volume de données et ceci sans  interruption de service. L&#8217;opération de snapshot d&#8217;un EBS et de  recréation du volume est trop longue. LVM est la solution, puisque cette couche d&#8217;abstraction permet de gérer des volumes logiques de manière indépendante  des ressources physiques : il suffit de lever une nouvelle ressource EBS  (une ligne de commande), de l&#8217;associer à l&#8217;instance EC2 (une autre  ligne de commande) et d&#8217;ajouter cette ressource au pool de ressources  LVM. Il suffit alors d&#8217;agrandir le volume logique (toujours transparent et sans arrêt du service), puis  d&#8217;étendre le système de fichiers. C&#8217;est la dernière  opération (qui est commune avec celle de la recréation du volume EBS) qui peut nécessiter d&#8217;arrêter le service quelques instants (une dizaine de secondes). A noter qu&#8217;il est possible d&#8217;étendre son système de fichiers à chaud avec EXT3, personnellement, je préfère une interruption de service de quelques secondes sur ce genre d&#8217;opérations très courtes mais cruciales. ;ob En  prime, il est facile de d&#8217;effectuer des backups sur un système LVM qui  propose une option de snapshot différentiel que l&#8217;on peut monter comme  un volume logique indépendant : lorsqu&#8217;il y a une modification sur le  volume origine, la valeur initiale est copiée dans le volume snapshoté,  donc on peut snapshoter des volumes importants sur un espace réduit car  seule la fréquence de modification est importante. Vous pourrez trouver de plus amples informations sur LVM2 et EBS en consultant ce <a title="Decrypt, EBS et LVM2 ou comment optimiser l’élasticité des AWS" href="http://decrypt.ysance.com/2010/06/ebs-et-lvm2-ou-comment-optimiser-elasticite-des-aws/">très bon article</a> de Laurent Roux.</p>
<p>Tous ces exemples, pour montrer que les EBS sont une ressource très  intéressante : il faut les considérer tout d&#8217;abord comme un moyen d&#8217;assurer la durabilité des ressources importantes avant de considérer l&#8217;aspect performance. En effet, la performance n&#8217;est pas forcément meilleure sur un EBS que sur les disques locaux d&#8217;une instance EC2 (Cf. <a title="Ma petite présentation au Amazon web service french user group 2010" href="http://www.karlesnine.com/post/2010/05/07/Amazon-web-service-french-user-group-2010">un test simple et intéressant</a> de Charles-Christian Croix ou bien encore des tests un peu plus complexes que vous pourrez retrouver en tapant <em>&laquo;&nbsp;performance ephemeral disk ebs volume raid&nbsp;&raquo;</em> dans Goggle, il y en a un certain nombre de très intéressants et je dois avouer que j&#8217;ai du mal à faire mon choix ;ob). Cependant, quand on prend le parti d&#8217;assurer la durabilité de ses données et donc d&#8217;utiliser un EBS (qui, pour ceux qui connaissent, est comparable à un LUN sur un SAN), il y a divers moyens d&#8217;optimiser leur performance.</p>
<p>Il est à noter que les utiliser pour répartir les fichiers (et donc les I/O) sur plusieurs disques EBS peut être une solution de performance pure.</p>
<p>A noter tout de même que la bande passante de l&#8217;EC2 est forcément limitant arrivée à un certain seuil : ajouter des EBS est intéressant pour lisser les écarts de variance (en RAID0) ou bien pour optimiser le débit, mais il n&#8217;en reste pas moins que si vous ajoutez plusieurs EBS à votre instance EC2 et qu&#8217;ils sont tous sollicités fortement&#8230; C&#8217;est la bande passante de l&#8217;EC2 qui bloque. Il va falloir ajouter un nouvel EC2 (scale-out pour augmenter les ressources, en l&#8217;occurrence la bande passante), lui attacher de nouveaux EBS (n&#8217;oubliez pas qu&#8217;un EBS ne peut être attaché qu&#8217;à un et un seul EC2) et distribuer la donnée dessus (sharding).</p>
<p>Dans tous les cas, la manipulation des EBS est aisée et cette souplesse est un  atout.</p>
<p><em><strong>Tips &amp; tricks</strong></em><br />
Cette dernière partie regroupe quelques trucs et astuces.</p>
<p><em><span style="text-decoration: underline;">Alias &amp; IPs</span></em><br />
Pensez sur une infrastructure AWS à positionner des alias  correspondant aux IPs privées de vos instances dans le fichier des &laquo;&nbsp;hosts&nbsp;&raquo;, que vous pouvez déployer ensuite via <a title="Site de Puppet" href="http://www.puppetlabs.com/">Puppet</a> pour plus de réactivité vu que les IPs sont &laquo;&nbsp;variables&nbsp;&raquo; (lorsque vous arrêtez une instance et que vous en redémarrez une juste après, vous ne conservez pas la même IP). L&#8217;utilisation du  fichier &laquo;&nbsp;hosts&nbsp;&raquo; évite des résolutions DNS internes chez Amazon.</p>
<p><em><span style="text-decoration: underline;">CDN &amp; S3 Headers</span></em><br />
Pour les CDN (Content Delivery Network) que vous utilisez  obligatoirement dans une architecture scalable, pensez à utiliser S3 afin  de mettre à disposition les images et autres contenus statiques.  Inutile de maintenir un serveur Web à cette seule fin, S3 est là pour ça  pour un coût minime.</p>
<p>Pensez également dans certains cas où votre trafic est plus modéré et que vous ne souhaitez pas passez sur un CDN (pour des questions de coût par exemple ;ob), que vous pouvez toujours optimiser la gestion de vos ressources sur S3 en utilisant les méta-données attribuées aux dites ressources sur S3, en positionnant, par exemple, les headers de type <em>Cache-Control</em> ou <em>Expires</em>. Vous pouvez visualiser ces méta-données via le nouvel <a title="Site de Amazon Web Services, Console AWS, Onglet S3" href="https://console.aws.amazon.com/s3/home">onglet S3</a> de la console d&#8217;administration Amazon.</p>
<p><span style="text-decoration: underline;"><em>Backups&#8230;</em><em> What else ?</em></span><br />
S3 est également la solution pour les backups. Je n&#8217;ai pas trouvé  d&#8217;outils intégré satisfaisant pour cette tâche : j&#8217;utilise simplement un  outil en ligne de commande &laquo;&nbsp;<a title="Site de s3tools, s3cmd" href="http://s3tools.org/s3cmd">s3cmd</a>&nbsp;&raquo; afin de stocker mes backups. J&#8217;ai intégré cet  outil dans des tâches <a title="Site de Capistrano" href="http://www.capify.org/">Capistrano</a> appelées par cron. Très  simple d’utilisation, s3cmd permet de consommer les services de S3 et offre la  possibilité de transférer les données en HTTPS et également de les  stocker sous un format crypté.</p>
<p><em><strong>Conclusion</strong></em><br />
Il y aurait encore beaucoup de choses à dire sur ce sujet, mais ce  sont à mon avis les principales, en tout cas par rapport à l&#8217;utilisation des services mis à disposition par les AWS. Ce qu&#8217;il en ressort, c&#8217;est :</p>
<ul>
<li>Le stateless et REST de manière générale, sont d&#8217;autant plus adaptés aux AWS qu&#8217;ils permettent de distribuer aisément la charge sur une infrastructure s&#8217;adaptant à la montée en charge sur un modèle scale-out.</li>
<li>L&#8217;accès aux données est toujours le goulet d&#8217;étranglement des applications distribuées devant scaler. Il s&#8217;agit de travailler à ce niveau le modèle de données et de tirer parti des systèmes de stockage adéquates :
<ul>
<li>Technologies SQL pour les méta-données pouvant nécessiter du requêtage ensembliste et de la mise en  relation, tout en utilisant au maximum un cache réseau pour les informations avec un fort ratio lecture sur écriture.</li>
<li>Technologies NoSQL / Not only SQL / clé-valeur pour les informations pouvant être accédées par une clé unique, et ainsi bénéficier de la distribution inhérente au scale-out.</li>
</ul>
</li>
<li>Penser finalement aux couches basses en sélectionnant convenablement le système de fichiers et l&#8217;ordonnanceur. Pensez également RAID (striping) et LVM (extension de volume et snapshot différentiel) pour tirer parti de la souplesse d&#8217;utilisation des EBS et répartition des I/O sur différents devices (en prenant toujours garde à votre bande passante, au niveau EC2, qui peut devenir limitant : dans ce cas ajouter une ou plusieurs instances EC2 pour gagner en bande passante et distribuer &#8211; sharder &#8211; la donnée sur de nouveaux EBS).</li>
</ul>
<p>J&#8217;espère que ce deuxième volet de mon retour d&#8217;expérience sur la scalabilité des infrastructures AWS vous aura intéressé.</p>
<p><em><strong>Frédéric FAURE</strong></em> <a title="Frédéric FAURE @Twitter" href="http://twitter.com/fredericfaure">@Twitter</a> <a title="Ysance, Simplifions les projets informatiques" href="http://www.ysance.com/">@Ysance</a></p>
]]></content:encoded>
			<wfw:commentRss>http://decrypt.ysance.com/2010/07/scaler-une-infrastructure-aws-2-le-modele/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tokyo Tyrant / Tokyo Cabinet, un key-value store à la Japonaise</title>
		<link>http://decrypt.ysance.com/2009/12/tokyo-tyrant-tokyo-cabinet-key-value-store-japonaise/</link>
		<comments>http://decrypt.ysance.com/2009/12/tokyo-tyrant-tokyo-cabinet-key-value-store-japonaise/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 15:20:34 +0000</pubDate>
		<dc:creator>Frédéric Faure</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Sharding / Partitionnement]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[Tokyo Cabinet]]></category>
		<category><![CDATA[Tokyo Tyrant]]></category>

		<guid isPermaLink="false">http://decrypt.ysance.com/?p=648</guid>
		<description><![CDATA[Les bases de données non relationnelles sont mises en avant depuis quelques temps avec un panel important de systèmes de stockage de la forme clé/valeur (key/value store). Cette approche permet d'avoir des structures optimisées pour certains types de fonctionnel et facilement distribuables. <a title="Site de Tokyo Cabinet" href="http://1978th.net/tokyocabinet/">Tokyo Cabinet</a> est un de ces outils. C'est un outil de stockage clé/valeur open source sponsorisé et utilisé par Mixi (Facebook japonais). Il a été développé par Mikio Hirabayashi que vous pouvez retrouver ainsi que l'exhaustivité des produits qu'il met à disposition sur <a title="Mikio Hirabayashi's homepage" href="http://1978th.net/">Mikio Hirabayashi's homepage</a>. Tokyo Cabinet est couplé à un autre produit : <a title="Site de Tokyo Tyrant" href="http://1978th.net/tokyotyrant/">Tokyo Tyrant</a>. Tokyo Tyrant est en fait l'interface réseau qui permet, entre autre, d'accéder à partir d'un serveur distant à Tokyo Cabinet. Il ne se limite cependant pas à cela et permet un certain nombre de fonctionnalités très intéressantes. Le point fort de ce couple est la rapidité de traitement des requêtes, ainsi que les possibilités de mise en oeuvre.

[...]]]></description>
			<content:encoded><![CDATA[<p>Les bases de données non relationnelles sont mises en avant depuis quelques temps avec un panel important de systèmes de stockage de la forme clé/valeur (key/value store). Cette approche permet d&#8217;avoir des structures optimisées pour certains types de fonctionnel et facilement distribuables. <a title="Site de Tokyo Cabinet" href="http://1978th.net/tokyocabinet/">Tokyo Cabinet</a> est un de ces outils. C&#8217;est un outil de stockage clé/valeur open source sponsorisé et utilisé par Mixi (Facebook japonais). Il a été développé par Mikio Hirabayashi que vous pouvez retrouver ainsi que l&#8217;exhaustivité des produits qu&#8217;il met à disposition sur <a title="Mikio Hirabayashi's homepage" href="http://1978th.net/">Mikio Hirabayashi&#8217;s homepage</a>. Tokyo Cabinet est couplé à un autre produit : <a title="Site de Tokyo Tyrant" href="http://1978th.net/tokyotyrant/">Tokyo Tyrant</a>. Tokyo Tyrant est en fait l&#8217;interface réseau qui permet, entre autre, d&#8217;accéder à partir d&#8217;un serveur distant à Tokyo Cabinet. Il ne se limite cependant pas à cela et permet un certain nombre de fonctionnalités très intéressantes. Le point fort de ce couple est la rapidité de traitement des requêtes, ainsi que les possibilités de mise en oeuvre.</p>
<p>Pour servir de support à cet article, je vous propose de regarder cette vidéo très intéressante de Ilya Grigorik, fondateur et CTO de AideRSS, que vous pourrez retrouver sur son blog <a title="Site de Ilya Grigorik" href="http://www.igvita.com/">igvita.com</a> (un blog très intéressant que je vous conseille de lire).</p>
<p>La <a title="Lean &amp; Mean Tokyo Cabinet Recipes" href="http://www.infoq.com/presentations/grigorik-tokyo-cabinet-recipes">VIDEO</a>.</p>
<p>Cette vidéo de 30 min, dans un anglais tout à fait abordable, est très intéressante, notamment sur les extensions de fonctionnalités rendues possibles par le langage de scripting Lua, intégrable au niveau de Tokyo Tyrant afin de permettre la mise en place de &laquo;&nbsp;user-defined fonctions&nbsp;&raquo; au niveau du serveur, centralisant les traitements et les rendant pseudo-atomiques. Je reviendrai dessus par la suite.</p>
<p><strong><em>Les APIs</em></strong><br />
Comme je vous le précisais, Tokyo Tyrant/Tokyo Cabinet est un couple gérant respectivement les requêtes à partir de serveurs distants (interface réseau) et les accès au système de stockage. 6 APIs sont disponibles afin de stocker les données :</p>
<ol>
<li>On memory Hash,</li>
<li>On memory B+tree,</li>
<li>File Hash,</li>
<li>File B+tree,</li>
<li>Fixed-length Array,</li>
<li>Table.</li>
</ol>
<p>Chacune d&#8217;entre elles a ses propres spécificités et répond à des besoins particuliers en termes de performances et de fonctionnalités.</p>
<p>Je ne paraphraserai pas la vidéo de Ilya Grigorik qui explique déjà un certain nombre de choses, mais apporterai quelques précisions.</p>
<p>Sur la notion de complexité des mécanismes de stockage Hash et B+tree (On memory ou File), les fonctions O(1) et O(log N) représentent la complexité d&#8217;accès à la donnée en fonction du nombre d&#8217;occurences stockées dans le système. On comprend bien que le comportement O(1) correspond bien à celui d&#8217;une hashtable, puisque le temps d&#8217;accès à la donnée ne dépend pas du nombre d&#8217;occurrences. En effet, la donnée est accédée directement à partir du hash de sa clé. Eventuellement, cette complexité peut varier si des collisions sur le hash apparaissent (2 clés différentes peuvent donner le même hash, à ce hash correspond alors une liste chainée de valeurs possibles). Il n&#8217;y a pas non plus d&#8217;index et donc de reconstruction d&#8217;index sur les insertions : donc gain de rapidité par rapport à une base de données classique. Pour plus de détail sur le fonctionnement des hashtables suivez ce <a title="Hash table, From Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Hash_table">lien</a>. Voici également 2 schémas issus de &laquo;&nbsp;Wikipedia, the free encyclopedia&nbsp;&raquo; expliquant la notion de hash et de collision :</p>
<div id="attachment_735" class="wp-caption alignnone" style="width: 325px"><img class="size-full wp-image-735" title="Hashtable" src="http://decrypt.ysance.com/wp-content/uploads/2009/12/Hashtable.png" alt="Hashtable" width="315" height="230" /><p class="wp-caption-text">Hashtable</p></div>
<div id="attachment_736" class="wp-caption alignnone" style="width: 460px"><img class="size-full wp-image-736" title="Hashtable - Collisions" src="http://decrypt.ysance.com/wp-content/uploads/2009/12/HashtableCollisions.png" alt="Hashtable - Collisions" width="450" height="310" /><p class="wp-caption-text">Hashtable - Collisions</p></div>
<p>La notion permettant d&#8217;évaluer la probabilité de collision est ce que l&#8217;on appelle la dispersion&#8230; Mais cela est un autre sujet ! ;ob</p>
<p>On comprend que le B+tree est donc un peu moins performant car sensible dans une certaine mesure (O(log N)) au nombre d&#8217;enregistrements. B+tree trouve son utilité dans le fait que le stockage est moins volumineux sur disque (ou en mémoire). Dans le cas du B+tree, les clés ne sont pas nécessairement uniques et il y a une notion de tri.</p>
<p>Pour le détail sur ces APIs, vous pouvez consulter la <a title="Fundamental Specifications of Tokyo Cabinet Version 1" href="http://1978th.net/tokyocabinet/spex-en.html">spécification</a>.</p>
<p><strong><em>Les performances</em></strong><br />
Il est à noter que les performances atteintes par Tokyo Cabinet seront probablement limitées du fait de l&#8217;utilisation de Tokyo Tyrant, puisque dans la majorité des cas vous aurez probablement à accéder au système de stockage à partir d&#8217;un serveur distant. Partez donc sur les performances affichées par Tokyo Tyrant qui, soit dit en passant, sont déjà considérables. Lors d&#8217;un bench que j&#8217;ai effectué sur le produit, je me suis aperçu que le load average de mon serveur hébergeant Tokyo Tyrant et Tokyo Cabinet était anormalement élevé&#8230; Pas à cause du CPU, mais à cause du disque qui ne répondait pas assez vite aux I/O débités par la Tokyo Team&#8230; Pensez à bien choisir votre système de fichier dans ce cas (type &#8211; EXT3, XFS, &#8230; -, journalisé ou non, options de montage, &#8230;) et n&#8217;hésitez pas à mettre du RAID0, par exemple, pour optimiser les performances en lecture/écriture ou bien à répartir les écritures des différents fichiers physiques (données, ulogs, &#8230;) sur différents disques.</p>
<p>Est-il nécessaire de préciser que ce qui vous prendra du temps sur l&#8217;accès à une donnée via le réseau c&#8217;est&#8230; Le réseau ! Hé oui ! Donc dans tous les cas préférez l&#8217;utilisation au niveau client (API) de &laquo;&nbsp;mget&nbsp;&raquo; (multi get), par exemple, en positionnant en paramètre le tableau de clés que vous souhaitez récupérer, plutôt que d&#8217;effectuer N fois un &laquo;&nbsp;get&nbsp;&raquo; à partir du client, donc N accès réseau. &laquo;&nbsp;mget&nbsp;&raquo; se résoudra, lui, au niveau serveur (Tokyo Tyrant).</p>
<p><strong><em>Les protocoles</em></strong><br />
Il est à noter que les protocoles HTTP et Memcached (et donc leurs APIs) sont directement utilisables afin d&#8217;accéder à Tokyo Tyrant, pas besoin de modifier le code de l&#8217;application pour passer d&#8217;un stockage on-memory sur <a title="Site de Memcached" href="http://memcached.org/">Memcached</a> à un stockage on-file sur Tokyo Tyrant/Tokyo Cabinet, par exemple. A noter que l&#8217;intégralité des fonctionnalités de Tokyo Tyrant ne seront donc pas forcément disponibles via le protocole Memcached ou HTTP, comme la concaténation, &#8230; Vous pouvez également utiliser le protocole natif binaire pour communiquer avec Tokyo Tyrant, ou bien avec Tokyo Cabinet si vous fonctionnez en &laquo;&nbsp;localhost&nbsp;&raquo;.</p>
<p><em><strong>Le requêtage ensembliste</strong></em><br />
En utilisant l&#8217;API Table, vous remarquerez qu&#8217;à chaque clé correspond un ensemble d&#8217;attributs, pas forcément le même nombre pour chaque clé (ces attributs peuvent être ajoutés à la volée et pas forcément valorisés pour les clés &laquo;&nbsp;antérieures&nbsp;&raquo;&#8230; Ni &laquo;&nbsp;postérieures&nbsp;&raquo; d&#8217;ailleurs). Il n&#8217;y a donc pas de schéma figé et chaque attribut peut faire l&#8217;objet d&#8217;une clause de requête ensembliste de type &laquo;&nbsp;WHERE&nbsp;&raquo;. Vous pourrez donc récupérer une liste de valeurs correspondant à des conditions sur un attribut et n&#8217;avez pas besoin de nommer explicitement la clé ou un pattern de clé afin de récupérer votre objet ou votre liste d&#8217;objets (cela n&#8217;est possible qu&#8217;avec l&#8217;API Table). Ce fonctionnement est similaire à celui que l&#8217;on peut retrouver sur <a title="Site de Amazon Web Services, Rubriques SimpleDB" href="http://aws.amazon.com/simpledb/">SimpleDB</a>, par exemple. A noter qu&#8217;il est aussi possible de positionner un index sur un attribut (Cf. vidéo de Ilya Grigorik).</p>
<p><strong><em>Lua</em></strong><br />
Lua&#8230; Lua !!! Un langage de scripting léger et efficace et comme le dit Ilya Grigorik : &laquo;&nbsp;C&#8217;est un mélange de Ruby et de Javascript&#8230; Enfin&#8230; Les mauvaises choses des 2 ! ;ob&nbsp;&raquo;. Cela explique probablement sa popularité : facile à utiliser, simple, efficace, &#8230; que demander de plus ? Il permet, par comparaison avec MySQL, de mettre en place des &laquo;&nbsp;user-defined fonctions&nbsp;&raquo;, à la différence qu&#8217;il s&#8217;agit d&#8217;un langage interprété qui ne provoquera pas le plantage du serveur Tokyo Tyrant sur une erreur ;ob. Il permet de mettre en place des opérations complexes comme par exemple :</p>
<ul>
<li>Renvoyer les données avec un format particulier (JSON, &#8230;).</li>
<li>Implémenter des fonctionnalités pseudo-atomiques au niveau serveur (c&#8217;est à dire atomique vu par le client = un seul appel réseau) afin de reproduire des fonctionnements tels que ceux du composant Set de <a title="Site de Redis" href="http://code.google.com/p/redis/">Redis</a>, un autre système de stockage clé/valeur montant l&#8217;intégralité de son dataset en mémoire (il faut tenir compte de ce point quand on choisit Redis au regard du volume de données que l&#8217;on doit stocker, mais rien n&#8217;empêche de distribuer le dataset sur plusieurs Redis) et assurant la persistance des données en écrivant de manière asynchrone sur le disque (soit suivant un délai, soit suivant un nombre de modifications effectuées sur ledit dataset). Concernant les types de données natifs sous Redis, vous pourrez notamment trouver les &laquo;&nbsp;List&nbsp;&raquo; qui sont des séquences d&#8217;éléments ordonnées et les &laquo;&nbsp;Set&nbsp;&raquo; (évoqués dans la vidéo) correspondant à une collection non-ordonnée sur laquelle on peut appliquer des opérations de type intersection, union, différence, &#8230; avec d&#8217;autres &laquo;&nbsp;Set&nbsp;&raquo;. Pour terminer cette digression permettant de comprendre l&#8217;exemple donné au cours de la vidéo, vous pouver consulter la <a title="Page de référence des commandes Redis" href="http://code.google.com/p/redis/wiki/CommandReference">Page de référence des commandes Redis</a>, ainsi que l&#8217;<a title="Introduction aux types de données Redis" href="http://code.google.com/p/redis/wiki/IntroductionToRedisDataTypes">Introduction aux types de données Redis</a>. Un exemple/tutoriel très intéressant est également disponible et présente la mise en place d&#8217;un clone de Twitter nommé Retwis : <a title="A case study: Design and implementation of a simple Twitter clone using only the Redis key-value store as database and PHP" href="http://code.google.com/p/redis/wiki/TwitterAlikeExample">A case study: Design and implementation of a simple Twitter clone using only the Redis key-value store as database and PHP</a>.</li>
<li>Implémenter une notion de TTL (Time To Live) comme dans Memcached. Cet exemple est basé sur l&#8217;utilisation de la Table API, puisqu&#8217;il faut un attribut supplémentaire ( &laquo;&nbsp;l&#8217;expiration time&nbsp;&raquo; ) qu&#8217;il est commode d&#8217;indexer pour des questions de performances (la possibilité d&#8217;introduire des index est noter pour cette API).</li>
</ul>
<p>A noter que ces implémentations, et notamment celle du Set, ne sont probablement pas aussi rapides qu&#8217;une fonctionnalité native, mais il est très pratique de pouvoir embarquer de la logique au niveau du serveur.<br />
A noter également la possibilité de démarrer le serveur Tokyo Tyrant en demandant un appel périodique (pc = periodic call) à ces &laquo;&nbsp;user-defined fonctions&nbsp;&raquo; en background. Pratique pour des opérations de purge, &#8230;</p>
<p><strong><em>MapReduce inside !</em></strong><br />
On note l&#8217;introduction du paradigm MapReduce à l&#8217;intérieur de Tokyo Tyrant, en natif, avec la possibilité de développer ses fonctions de Map et de Reduce en Lua.</p>
<p><strong><em>Réplication</em></strong><br />
Il est également possible de mettre en place de la réplication master-slave simplement entre 2 serveurs : quel beau couple qu&#8217;un master &laquo;&nbsp;on-memory&nbsp;&raquo; permettant d&#8217;optimiser les accès et un slave &laquo;&nbsp;on-file&nbsp;&raquo; assurant la persistance des données.</p>
<p>Voici les commandes permettant de mettre 2 serveurs en master-slave :</p>
<blockquote><p>ttserver -port 1978 -ulog ulog-1 -sid 1 casket-1.tch<br />
ttserver -port 1979 -ulog ulog-2 -sid 2 -mhost localhost -mport 1978 -rts 2.rts casket-2.tch</p></blockquote>
<p>Simple non ?</p>
<p><strong><em>Conclusion</em></strong><br />
Tokyo Tyrant / Tokyo Cabinet est un outil de stockage clé/valeur très intéressant, d&#8217;une part par ses performances et d&#8217;autre part par les possibilités d&#8217;évolutions qu&#8217;il offre en termes de fonctionnalités et de logique embarquée.</p>
<p>Cependant au delà de l&#8217;outil lui-même, il faut se poser la question en amont du modèle que l&#8217;on souhaite adopter vis à vis du fonctionnel de son application. Il est évident que si votre application peut s&#8217;adapter à un modèle clé/valeur, il est indispensable d&#8217;envisager cette possibilité, et c&#8217;est une des premières étapes à envisager au niveau de la conception. Je cite un de mes articles concernant le <a title="Sharding et optimisation des accès aux données" href="http://decrypt.ysance.com/2009/05/sharding-partitionnement-optimisation-acces-aux-donnees/">Sharding et optimisation des accès aux données</a> :</p>
<blockquote><p>Le sharding est une des solutions possible pour l’amélioration des temps de réponse sur ladite source d’éléments. Mais avant d’envisager cette solution, il est intéressant d’envisager d’autres possibilités dans cet ordre :</p>
<p>• le concept du modèle non relationnel, hébergé ou non, en général, puisque de ce choix découlera un autre modèle de fonctionnement,</p></blockquote>
<p>Le modèle clé/valeur est en effet un boost en termes de performances, si évidemment celui-ci correspond à votre fonctionnel. Cette question est à soulever rapidement et permettra de ne pas partir sur un modèle relationnel trop coûteux et sous exploité par certains types d&#8217;application.</p>
<p><strong><em>Frédéric FAURE</em></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://decrypt.ysance.com/2009/12/tokyo-tyrant-tokyo-cabinet-key-value-store-japonaise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharding et optimisation des accès aux données</title>
		<link>http://decrypt.ysance.com/2009/05/sharding-partitionnement-optimisation-acces-aux-donnees/</link>
		<comments>http://decrypt.ysance.com/2009/05/sharding-partitionnement-optimisation-acces-aux-donnees/#comments</comments>
		<pubDate>Thu, 28 May 2009 18:40:34 +0000</pubDate>
		<dc:creator>Frédéric Faure</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Sharding / Partitionnement]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Memcached]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Partitionnement]]></category>
		<category><![CDATA[Proxy MySQL]]></category>
		<category><![CDATA[Réplication]]></category>
		<category><![CDATA[SimpleDB]]></category>

		<guid isPermaLink="false">http://decrypt.ysance.com/?p=172</guid>
		<description><![CDATA[Le sharding ou partitionnement de données entre dans le cadre plus global de la scalabilité. Il s’agit tout simplement du découpage des données d’une base afin d’avoir à requêter sur moins d’occurrences et donc d’avoir un résultat plus rapide donc de meilleures performances. Le sharding est une solution à part entière, mais qui ne convient pas dans tous les cas. Nous verrons également quelles sont les solutions alternatives pour une amélioration des temps de réponse au niveau d’une base de données.

[...]]]></description>
			<content:encoded><![CDATA[<p>Le sharding ou partitionnement de données entre dans le cadre plus global de la scalabilité. Il s’agit tout simplement du découpage des données d’une base afin d’avoir à requêter sur moins d’occurrences et donc d’avoir un résultat plus rapide donc de meilleures performances. Le sharding est une solution à part entière, mais qui ne convient pas dans tous les cas. Nous verrons également quelles sont les solutions alternatives pour une amélioration des temps de réponse au niveau d’une base de données.</p>
<p><strong><em>Pourquoi est-il si méchant ?</em></strong><br />
Oui ? Pourquoi vouloir à tout prix découper cette pauvre donnée dans tous les sens ? Quel est le déclencheur de cet acte barbare ?</p>
<p>Cela se produit simplement quand les temps de réponse des opérations sur une table fortement peuplée deviennent trop importants. Nous prendrons comme exemple une table « utilisateurs » comportant plusieurs millions de lignes. Depuis de nombreux SELECT en concurrence, qui unitairement ne présentent pas de performances dégradées malgré le nombre d’enregistrements, mais qui, sur de nombreuses requêtes, accumulent les latences, jusqu’aux INSERT demandant de reconstruire des INDEX monstrueux, où quelques insertions en trop sature la base, il y a de nombreuses raisons évidentes de vouloir découper son pool de données afin de pouvoir les manipuler plus légèrement.</p>
<p>Pour résumer, le besoin peut provenir de la masse de données elle-même ou bien du nombre/type de requêtes sur cette masse.</p>
<p>Il existe à ce niveau 2 techniques de sharding : le découpage en tranches et en lamelles…</p>
<p><strong><em>Découpage en tranches… ou horizontal</em></strong><br />
Le sharding horizontal consiste à répartir les données (lignes) d’une table cible entre plusieurs selon un critère basé sur une information liée à la donnée, par exemple un modulo sur l’identifiant qui permet de répartir les données sur X tables. Le tout est de savoir, au niveau de l’application cliente, sur quelle table aller chercher l’information. La clé et le plan de répartition sont , en effet, des éléments déterminants. La clé étant l’élément (ou les éléments) de la donnée à répartir sur lequel (ou lesquels) va porter le plan.</p>
<p>Plusieurs plans de répartition sont possibles sur une clé donnée :</p>
<p style="padding-left: 30px;">• Le modulo comme cité précédemment, ou autre fonction mathématique adaptée, est une option possible. Cependant, un changement du nombre de shard implique une redistribution complète. C’est cependant pratique si on doit définir la répartition sur un identifiant que l’on ne maitrise pas (récupéré d’un autre système ou fournisseur par exemple).</p>
<p style="padding-left: 30px;">• Dans la même idée, on peut répartir selon un algorithme de hash à définir soigneusement sur des valeurs non modifiables pour un objet donné à répartir et de telle manière que le calcul du hash soit rapide, le nombre de collisions entre 2 résultats minimum et la dispersion bonne. De même que précédemment, un changement du nombre de shard peut impliquer une redistribution complète. Cependant, des algorithmes appelés « consistants » existent. En utilisant des algorithmes de hash consistants, seulement K/n clés doivent être redistribuées en moyenne, où K est le nombre total de clés et n le nombre de shards.</p>
<p style="padding-left: 30px;">• Un « range », c&#8217;est-à-dire un intervalle, est aussi une solution. Pratique pour étendre le nombre de shard, il faut cependant maitriser l’identifiant retenu, un incrément par exemple, afin d’avoir une diffusion correcte.</p>
<p>D’autres méthodes peuvent êtres envisagées. Celles que j’ai citées sont les plus communes et les plus utilisées car elles répondent en général au besoin. La diffusion de la méthode retenue sur le critère choisi est dans tout les cas à vérifier pour une répartition efficace des données, c&#8217;est-à-dire qu’une répartition efficace aboutit à l’obtention de shards de tailles équivalentes. Le critère choisi pour répartir est généralement un identifiant, en effet, toute modification de la valeur déterminant la répartition, dans le cas d’un range ou bien intégrée dans le calcul d’un hash ou d’une fonction mathématique, ferait que l’objet ne serait plus accessible car pas enregistré dans le shard lui correspondant ou alors il faudrait le redispatcher…</p>
<p>Cette répartition peut se faire sur X tables dans une même base ou serveur ou bien sur 1 table dans Y bases ou serveurs (ou les 2 ;ob). Tout dépend du point d’engorgement. Est-ce purement le temps de réponse dû au volume de la table ? Ou bien atteint-on la limite physique du serveur qui peine à répondre à toutes ces requêtes ?</p>
<p>On en vient à la limitation de ce modèle pour lequel les requêtes ensemblistes posent problème. Je m’explique : on répartit les utilisateurs dans 2 tables en fonction du sexe : homme / femme. Je souhaite récupérer via une requête unitaire le Monsieur dont l’identifiant est X. Pas de problème je « SELECT * FROM UTILISATEUR_HOMME WHERE id=X ». Maintenant je souhaite récupérer toutes les personnes possédant un numéro de portable… Il va falloir faire la requête sur les 2 tables et corréler les résultats au niveau applicatif… dans des requêtes plus compliquées, notamment incluant des jointures, ce n’est pas forcément bénéfique. La parallélisation des requêtes, sur un sharding, au niveau applicatif est possible (quand le modèle de données le permet bien sûr), mais doit rester, à mon avis, mineur afin de ne pas perdre le bénéfice du sharding sur le temps de réponse pour une base donnée, en multipliant le nombre d’accès/connexions sur X sources et en traitant les résultats obtenus au niveau applicatif.</p>
<p>La répartition peut également engendrer des problèmes d’intégrité au niveau des données : la gestion des commit et des rollback est effective sur une connexion/transaction sur une base donnée. Comment gérer une transaction fonctionnelle qui s’étendrait sur plusieurs shard ? Commiter/rollbacker unitairement et prendre le risque d’une problématique d’intégrité ? Commiter/rollbacker chacune des connexions à la fin de la transaction fonctionnelle et conserver les connexions sur les X shards durant la transaction fonctionnelle et donc diminuer les capacités de connexions des X bases ?</p>
<p>Le problème de l’intégrité se pose également au niveau des backup/sauvegardes journalières, qui devront par conséquent s’effectuer lors d’une période de mise en maintenance (pas forcément longue) du site, nocturne par exemple. Il en va de même pour la restauration qui devra être effectuée, en cas de problème sur l’un des shards, sur l’ensemble des shards pour des problèmes d’intégrité.</p>
<p>On arrive enfin à la notion de « Single Point of Failure » dont le nombre augmentera avec le nombre de shards que vous mettrez en place sur des serveurs/machines différentes… A moins que vous ne fassiez de la réplication sur chacun des shards… Mais souvenez-vous qu’une solution efficace est bien souvent simple (ou tout du moins minimaliste) ! Alors…</p>
<p>Il n’y a pas de contre indication au sharding, il doit simplement être mesuré et prendre en compte les aspects précités afin d’être sûr que votre cas fonctionnel, et plus généralement votre besoin métier, accepte bien ce principe ou tout du moins en retire suffisamment de bénéfices pour valoir le jeu et être mis en place.</p>
<p><strong><em>Découpage en lamelles… ou vertical</em></strong><br />
Le sharding vertical se base sur une notion de temporalité. Plus simple à comprendre et à mettre en place, il dépend surtout de la typologie de votre site : un site marchand où 90% des visites du jour sont effectuées par des utilisateurs dont la connexion précédente à moins de 7 jours ou bien une administration dont 80% des dossiers consultés du jour l’ont déjà été dans les 2 dernières semaines. Ce n’est pas nécessaire de s’embêter à sharder si il n’y a pas de problématique de volumétrie, cependant, si le nombre d’informations trop important dans la table provoque des lenteurs sur la récupération/mise à jour/ajout d’informations et que la majeure partie des informations n’est que rarement utilisée… Bingo ! Il est intéressant de pouvoir donner à 90% (dans le premier cas) de vos visiteurs une expérience nettement meilleure tandis que les 10% restants auront une expérience quasi similaire, voire un peu dégradée dans le pire des cas.</p>
<p>L’étape la plus sensible sera de déterminer et d’ajuster au mieux la « coupure » de façon à satisfaire le plus grand nombre avec des performances optimales. C’est le moment d’analyser vos données et vos statistiques de fréquentation ! ;ob</p>
<p>Le mécanisme est très simple : quelque soit l’utilisateur, vous cherchez l’information dans la première table réduite contenant les données les plus accédées en un temps record, si elle y est tant mieux, sinon on requête dans la seconde table, celle des « archives ». il ne reste plus qu’à lancer un batch la nuit qui redispatche les éléments qui ont expiré de la table « courante » vers la table « archive » et de ramener les éléments archivés consultés ce jour vers la table courante.</p>
<p>Cette technique n’est absolument pas faite pour parer au problème du nombre d’accès/connexions à la base comme peut l’être le sharding horizontal, puisque le but est justement de satisfaire le plus rapidement possible la majeure partie des connexions à la dite base. Le but est purement de limiter la volumétrie d’une source de données pour en accélérer les traitements/requêtes dessus.</p>
<p>De plus, dans le cas de requêtes ensemblistes portant sur les 2 « zones », le problème est similaire à celui du découpage horizontal.</p>
<p><strong><em>Un petit cube, 2 petits cubes, …</em></strong><br />
Et les 2 en même temps ? Oui c’est possible ! Mais il faut satisfaire aux pré-requis des 2 cas et en accepter les bénéfices et inconvénients.</p>
<p><strong><em>Alternatives</em></strong><br />
Les alternatives proviennent du fait que le sharding répond à un besoin : celui d’améliorer les temps de réponse sur les accès aux sources de données. Mais d’autres solutions existent…</p>
<p><em><span style="text-decoration: underline;">L’essentiel tuning de base<br />
</span></em>Avant de se lancer dans du sharding et autres solutions plus complexes… Avez-vous paramétré convenablement votre base en fonction de l’utilisation que vous en faites ? Vous seriez surpris des différences que l’on peut obtenir… C’est LA première étape avant d’aller plus loin et d’envisager le sharding ou une autre solution. Une base convenablement tunée vous suffira peut-être.</p>
<p>Ensuite intéressez-vous au type de stockage. Il influe sur les performances en fonction des opérations effectuées. J’ai étudié le problème sur MySQL et constaté les différences flagrantes, en pratique, entre InnoDB et MyISAM. Pour les tables essentiellement accédées en lecture, MyISAM est fait pour. En revanche, pour celles accédées en écriture, InnoDB, avec son système de row locking, vous donnera bien meilleure satisfaction.</p>
<p>C’est LE conseil que je peux vous donner à cette étape : maitrisez d’abord votre outil de base (sans jeu de mots) avant de vouloir ajouter une couche de complexité, parfois nécessaire… Mais pas tout le temps.</p>
<p><em><span style="text-decoration: underline;">Le classique Master-Slave</span></em><br />
Le classique Master-Slave, encore appelé réplication, vous permettra d’optimiser des problèmes de temps de réponse dus au nombre de connexions/requêtes sur une table à forte volumétrie, où l’écriture peut prendre du temps du fait de la reconstruction d’index sur les INSERT par exemple et ce faisant influant sur les temps de réponse des lectures (SELECT) et vice-versa , en séparant la lecture de l’écriture : typiquement l’écriture s’effectuera sur le master et la lecture sur le slave (ou les slaves).</p>
<p><em><span style="text-decoration: underline;">L’éventuel partitionnement MySQL</span></em><br />
Depuis la version 5.1, MySQL propose un partitionnement (ou sharding) géré nativement. Ne l’ayant pas testé par moi-même, je ne pourrais vous donner de retour sur le sujet. Le partitionnement proposé par l’outil est horizontal. Il est à noter que la notion de partitionnement vertical est différente de celle que je vous est présentée dans la sémantique MySQL : il s’agit de pouvoir stocker sur différentes partitions les colonnes d’une même table, par exemple les colonnes de type standard d’une table donnée sur une partition et la colonne de type BLOB sur une autre. Dans tous les cas, le partitionnement vertical n’est pas assuré dans la version 5.1 de MySQL. Même si cela peut paraître attrayant, je pense qu’il est moins limitant de sharder soi-même et qu’il est rassurant de conserver la main sur la répartition des données que l’on souhaite et de pouvoir intervenir en toute connaissance de cause, sans se soucier, par exemple, de la version de la base et donc de la version de la fonctionnalité de partitionnement associée qui sous-tend la répartition des données, lors d’une montée de version… Je ne pense pas non plus qu’il soit possible d’effectuer un partitionnement « multi serveurs » afin de répartir le nombre de connexions entre diverses machines… Mais bon j’ai pas testé alors…</p>
<p><em><span style="text-decoration: underline;">Le « hors sujet » MySQL Proxy</span></em><br />
Compatible avec les versions 5.0.x de MySQL, cet outil est en version alpha et donc ne convient pas à un environnement de production. Mais le « hors sujet » ne provient pas de là mais du fait que cet outil traite de load balancing sur plusieurs backend (probablement des réplicats d’un master servant à une optimisation en lecture sur X slaves), de failover, et d’« injection SQL » permettant au niveau du proxy d’ajouter des clauses d’analyse aux requêtes ou bien de filtrer les résultats, … C’est l’équivalent d’un proxy web qui répartit la charge, gère le statut des backends et modifie les requêtes. Alors pourquoi est-ce que je parle de ça ? Hors sujet : 0/20 ! C’est uniquement parce que j’en ai entendu parler plusieurs fois de la part de clients et qu’il y avait une confusion sur son utilité. Le Proxy MySQL NE permet PAS de faire de la répartition de données.</p>
<p><em><span style="text-decoration: underline;">L’indispensable cache mémoire</span></em><br />
Je prendrai l’exemple de <a href="http://www.danga.com/memcached/" title="Site de Memcached">Memcached</a> qui est un cache de données réseau pour objets génériques. Memcached est le cache que j’utilise et qui a fait ses preuves. Maintenant, libre à vous d’utiliser d’autres outils ou bien même de réaliser vous-même votre système de cache mémoire adapté à votre utilisation, pour peu que vous en ayez l’envie et le temps. Dans tout les cas, votre cache mémoire vous permettra de limiter le nombre d’accès au système de stockage plus lent qu’est la base de données, en conservant un certain nombre de résultats dans une « hashtable géante ». En diminuant le nombre de requêtes sur vos tables volumineuses, cela suffira peut-être à obtenir des temps de réponse convenables et à ne pas saturer votre serveur en connexions, vous permettant ainsi de ne pas avoir à sharder.</p>
<p><em><span style="text-decoration: underline;">Le surprenant modèle non relationnel hébergé et SimpleDB</span></em><br />
Et oui ! Remis au goût du jour par Google avec BigTable et Amazon avec <a href="http://aws.amazon.com/simpledb/" title="Site de Amazon, rubrique SimpleDB">SimpleDB</a>, le modèle non relationnel prouve toute son efficacité et sa scalabilité. Si vous n’avez effectivement pas besoin des jointures et autres relations, c’est peut-être votre solution. Et pourquoi pas utiliser l’API Amazon pour SimpleDB et profiter de l’infrastructure et des services Amazon ?</p>
<p><em><span style="text-decoration: underline;">Les prometteuses innovations distribuées et Cassandra</span></em><br />
A rapprocher de SimpleDB car développé sur un modèle similaire à Dynamo, la technologie qui sous-tend simpleDB. <a href="http://incubator.apache.org/cassandra/" title="Site de Cassandra">Cassandra</a> est un système de stockage de données, structuré mais non relationnel, basé sur un réseau P2P (« peer to peer » ou « pair à pair » en Français ;ob). Il s’agit d’un système distribué sous forme de nodes, fortement scalable, et dont la particularité est qu’il est actuellement accessible au format Open Source. Développé par Facebook et actuellement en production chez eux, Cassandra est en version Beta et accessible dans le projet « Apache incubator » (Cf. liste de liens de la rubrique « Outils » de Decrypt : « Cassandra »). Vous pouvez également consulter cette note <a href="http://www.facebook.com/note.php?note_id=24413138919">http://www.facebook.com/note.php?note_id=24413138919</a> pour de plus amples informations. Il est surtout intéressant que l’explosion des applications et réseaux sociaux ait un impact sur la mise à disposition d’outils de stockage et de gestion de données fortement scalables. Cette tendance (augmentation de la volumétrie des données) va s’étendre à d’autres domaines du fait de la croissance des sources de données informatisées et de l’évolution des services. Les architectures distribuées se propagent jusqu’à la source… de données, dernier goulet d’étranglement des architectures scalables. Je pense cependant que le sujet de la scalabilité du système de stockage de données restera encore le point le plus ardu à mettre en place, pour un bout de temps, dans toute architecture.</p>
<p><strong><em>Conclusion</em></strong><br />
On constate que le sharding répond à un besoin bien particulier. Il concerne dans tous les cas une ou des tables contenant un volume important de données. Les lenteurs au niveau des temps de réponse peuvent être induites par le volume de données lui-même ou bien/et par le nombre d’utilisateurs s’y connectant de ce fait (dans le cas d’un site grand public). Le sharding est une des solutions possible pour l’amélioration des temps de réponse sur ladite source d’éléments. Mais avant d’envisager cette solution, il est intéressant d’envisager d’autres possibilités dans cet ordre :</p>
<p style="padding-left: 30px;">• le concept du modèle non relationnel, hébergé ou non, en général, puisque de ce choix découlera un autre modèle de fonctionnement,</p>
<p style="padding-left: 30px;">• le tuning de la base de données pour optimiser le socle de votre problématique,</p>
<p style="padding-left: 30px;">• le cache mémoire, simple de mise en place et terriblement efficace pour limiter les connexions inutiles sur votre source de données et livrer les informations en un temps record,</p>
<p style="padding-left: 30px;">• la réplication master-slave, classique mais efficace, dans la même optique de limitation du nombre de requêtes sur une base donnée,</p>
<p style="padding-left: 30px;">• les fonctionnalités de partitionnement livrées en natif avec le produit, potentiellement utiles, potentiellement limitées…</p>
<p style="padding-left: 30px;">• finalement le sharding (ou partitionnement) fait main ou plutôt les sharding, vertical et horizontal, pour limiter la volumétrie de la ou des tables, et par là même limiter le nombre de requêtes sur ladite ou lesdites tables dans le cas du sharding horizontal.</p>
<p>Il est tout à fait possible de composer en utilisant le cache mémoire avec la réplication, ou bien le cache mémoire avec un ou les 2 sharding… Le tout est de cibler son problème, le point d’engorgement et donc son besoin, pour utiliser la ou les techniques adéquates. Si une seule suffit, tant mieux.</p>
<p>Le sharding de données fait donc partie intégrante d’un problème plus global et est une solution tout à fait viable, demandant tout de même « un peu » de réflexion et de temps de mise en place et impactant dans la conception et la maintenance de l’infrastructure. Il est donc à utiliser à bon escient, mais se révèle fort utile et très efficace.</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><em><strong>Frédéric FAURE</strong></em></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"> </p>
]]></content:encoded>
			<wfw:commentRss>http://decrypt.ysance.com/2009/05/sharding-partitionnement-optimisation-acces-aux-donnees/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
