<?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>OCTO talks ! &#187; NoSQL</title>
	<atom:link href="http://blog.octo.com/tag/nosql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.octo.com</link>
	<description>Le blog d&#039;OCTO Technology, cabinet d&#039;architectes en systèmes d&#039;information</description>
	<lastBuildDate>Fri, 03 Feb 2012 13:46:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Une base de données purement fonctionnelle</title>
		<link>http://blog.octo.com/une-base-de-donnees-purement-fonctionnelle-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=une-base-de-donnees-purement-fonctionnelle-2</link>
		<comments>http://blog.octo.com/une-base-de-donnees-purement-fonctionnelle-2/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 09:24:44 +0000</pubDate>
		<dc:creator>Sebastian de Bellefon</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[programmation fonctionnelle]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=29640</guid>
		<description><![CDATA[Le modèle relationnel est né à une époque où l&#8217;espace était rare, et fut donc conçu pour minimiser le niveau de redondance des données: il était plus économique de stocker une indirection vers une chaine de caractères que de stocker cette chaine deux fois. Aujourd&#8217;hui, cette contrainte d&#8217;espace ne tient plus. On achète un Teraoctet [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/outiller-un-audit-de-base-de-donnees/' rel='bookmark' title='Outiller un audit de base de données'>Outiller un audit de base de données</a></li>
<li><a href='http://blog.octo.com/industrialisation-des-developpements-automatisez-votre-base-de-donnees/' rel='bookmark' title='Industrialisation des développements : automatisez votre base de données'>Industrialisation des développements : automatisez votre base de données</a></li>
<li><a href='http://blog.octo.com/des-alternatives-aux-bases-de-donnees-relationnelles%e2%80%a6/' rel='bookmark' title='Des alternatives aux bases de données relationnelles…'>Des alternatives aux bases de données relationnelles…</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fune-base-de-donnees-purement-fonctionnelle-2%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Une%20base%20de%20donn%C3%A9es%20purement%20fonctionnelle%22%20%7D);"></div>
<p><a href="http://blog.octo.com/wp-content/uploads/2012/01/PH33302.jpg"><img class="size-medium wp-image-29629" title="IBM 3330 Merlin" src="http://blog.octo.com/wp-content/uploads/2012/01/PH33302-300x169.jpg" alt="" width="300" height="169" /></a></p>
<p>Le modèle relationnel est né à une époque où l&#8217;espace était rare, et fut donc conçu pour minimiser le niveau de redondance des données: il était plus économique de stocker une indirection vers une chaine de caractères que de stocker cette chaine deux fois.<br />
Aujourd&#8217;hui, cette contrainte d&#8217;espace ne tient plus. On achète un Teraoctet pour 100 dollars, la RAM est abondante, et les disques flash aux performances élevées vont bientôt rejoindre le prix des disques durs rotatifs.</p>
<p>Deux limitations fondamentales du stockage ont donc disparu: le coût de la redondance et le coût de la non-localité pour le traitement de structures de données complexes. Il est maintenant possible de concevoir de nouvelles bases de données plus riches et plus sûres.</p>
<p><span id="more-29640"></span></p>
<blockquote><p>Update in place is a poison apple.<br />
- Jim Gray, Turing Award 1998</p></blockquote>
<p>Le choix d&#8217;une base de données mutables n&#8217;est plus optimal. Les bases de données purement fonctionnelles n&#8217;existent pas encore, mais je pense que les utilisateurs de bases de données auraient déjà intérêt à envisager le stockage read-only et le versioning manuel.</p>
<p>Que veut-on dire par &laquo;&nbsp;base de données mutables&nbsp;&raquo;? Il s&#8217;agit d&#8217;une BDD dans laquelle chaque donnée peut être modifiée à tout moment, et dans laquelle on ne garde pas l&#8217;historique de ses modifications. Les modifications sont faites &laquo;&nbsp;sur place&nbsp;&raquo;, de manière destructive.</p>
<p>Que veut-on dire par &laquo;&nbsp;base de données purement fonctionnelle&nbsp;&raquo;? Il s&#8217;agirait d&#8217;une BDD dans laquelle chaque structure de donnée serait <a href="http://en.wikipedia.org/wiki/Purely_functional">purement fonctionnelle</a>, c&#8217;est-à-dire immuable par défaut et ne ferait référence qu&#8217;à des données immuables. Pour prendre une analogie programmatique, cette BDD serait une interface vers des snapshots versionnés. Une sorte de Git!</p>
<p><strong>Vers une implémentation plus adaptée</strong></p>
<p>Les données d&#8217;une BDD méritent un traitement différencié en fonction de leurs patterns d&#8217;usage. Pourquoi par exemple, chez un grand opérateur téléphonique, devrait-on utiliser le même objet &laquo;&nbsp;table&nbsp;&raquo; pour référencer les monnaies, gérer la liste des clients et la liste des appels? Examinons leurs particularités. A partir de ces trois exemples simplifiés nous allons inférer plusieurs mécanismes fondamentaux d&#8217;une base de données purement fonctionnelle.</p>
<p>La liste de référence des monnaies est peu volumineuse. Elle est mise à jour quelques fois par an, tout au plus.<br />
La liste des clients de l&#8217;opérateur est moyennement volumineuse. Elle est mise à jour quotidiennement, avec quelques ajouts, suppressions et modifications aléatoires.<br />
La liste des appels est très volumineuse. Elle est mise à jour quotidiennement, mais seulement en insertion.</p>
<p>Nous avons donc au moins trois cas d&#8217;usage très différents. Or dans une BDD classique, ces trois données sont stockées de la même manière, c&#8217;est-à-dire sous la forme de listes mutables et indexées.<br />
Beaucoup d&#8217;effort a été investi pour améliorer les performances de ces tables avec le matériel donné, mais les solutions proposées sont encore très génériques.</p>
<p>Revenons à nos trois données. Il est possible de les implémenter autrement, en faisant appel à trois types d&#8217;objets:</p>
<ul>
<li>Des listes immuables (de type homogène, et implémentées par exemple par des hashtables sur la clef primaire)</li>
<li>Des deltas sur ces listes</li>
<li>Quelques métadonnées peu volumineuses qui serviront à articuler l&#8217;ensemble.</li>
</ul>
<p>La table des monnaies est l&#8217;exemple typique d&#8217;une liste simple et immuable. La liste d&#8217;aujourd&#8217;hui s&#8217;appelle la &#8216;v1&#8242;. Si demain une union monétaire est créée en Amérique du sud, nous créerons une copie modifiée qui s&#8217;appellera la &#8216;v2&#8242;. Pour des raisons de performance, la v1 et la v2 devront être copiées intégralement sur tous les noeuds de la base de données. La performance en update de cette implémentation est médiocre, mais toutes les lectures pourront être faites sans aucun mécanisme de synchronisation.</p>
<p>La table des clients est un peu plus volatile. Tous les jours quelques clients arrivent ou s&#8217;en vont, et quelques clients existants peuvent modifier leur adresse postale. Nous pouvons stocker la liste des clients comme une liste immuable &#8216;v1&#8242;, accompagnée par une séquence chronologique de deltas. D&#8217;ici à quelques mois, l&#8217;accumulation des deltas commencera à affecter la vitesse de lecture: il faudra alors matérialiser la liste, la nommer &#8216;v287&#8242; et archiver la v1. Dans le cas d&#8217;une machine seule, nous retrouvons presque exactement la manière dont Git stocke son historique. Dans le cas d&#8217;un cluster, il est bien sûr préférable de partitionner/sharder cette liste sur tous les nœuds.<br />
Selon quelle politique va-t-on vouloir archiver une version, la compresser ou la supprimer? Et selon quelles modalités? Chaque utilisateur doit prendre cette décision en fonction de ses besoins métier. Il est agréable, en tout cas, de remarquer que le <a href="http://searchstorage.techtarget.com/definition/data-life-cycle-management">Data Lifecycle Management</a> est offert sur un plateau par les BDD fonctionnelles.</p>
<p>La table des appels téléphoniques est différente. Chaque jour elle reçoit des milliers de nouvelles lignes, lesquelles sont parfaitement indépendantes des lignes antérieures. Cette liste est segmentable par journée, et chacun des segments quotidiens est une liste immuable. Nous devrions en plus partitionner chaque segment de manière à coller à la liste des clients: l&#8217;ID du client devient alors la clef de partitionnement des appels téléphoniques.</p>
<p>En résumé, à travers ces mécanismes de mise à jour, on accepte de consommer un peu plus d&#8217;espace disque, et de réduire la localité des données (car une nouvelle version ne sera probablement pas écrite à côté de l&#8217;ancienne). Tout cela pour garder une information plus riche.<br />
Remarquez bien que ces trois idées de versioning s&#8217;appliquent aussi bien à l&#8217;implémentation d&#8217;une nouvelle base de données qu&#8217;à une implémentation manuelle, basée sur les outils d&#8217;aujourd&#8217;hui.</p>
<p><strong>Conséquences</strong></p>
<p>Voilà pour les bases. Observons maintenant les conséquences positives de ces nouveaux choix d&#8217;implémentation.</p>
<p>Il devient possible par exemple:</p>
<ul>
<li>d&#8217;attribuer un identifiant unique à une version complète de la BDD, donc d&#8217;exécuter des requêtes de lecture sur une version du passé</li>
<li>d&#8217;effectuer un rollback à tout moment, en reprenant une ancienne version. Pas besoin d&#8217;attendre des heures pour recharger!</li>
<li>de paralléliser le requêtage à l&#8217;infini (car les listes immuables et les deltas sont triviaux à copier)</li>
<li>de hasher cryptographiquement le contenu (à la Git), pour un usage légal ou contractuel</li>
<li>de connaitre la séquence des processus qui ont fait évoluer la base ou une ligne en particulier</li>
<li>de diminuer le coût du backup et du Plan de Reprise d&#8217;Activité. Réaliser trois copies vers des disques sur étagère coûte peu (car les deltas sont copiables via des écritures non-aléatoires, donc rapides, et sans consommer de CPU)</li>
<li>de cacher le résultat de toute sorte de traitements, à la manière de vues matérialisées (filtrage, agrégation..)</li>
<li>de stocker dans la même BDD des objets classiques relationnels, et des objets plus variés (key-value store..)</li>
</ul>
<p>En l&#8217;absence d&#8217; &laquo;&nbsp;état global&nbsp;&raquo;, nous offrons aux processus d&#8217;alimentation et d&#8217;interrogation de la BDD tous les bénéfices de la programmation purement fonctionnelle. Ces processus deviennent <a href="http://fr.wikipedia.org/wiki/Transparence_r%C3%A9f%C3%A9rentielle">référentiellement transparents</a> (donc sans effet de bord), d&#8217;où une meilleure lisibilité pour les équipes de développement et de maintenance, et une diminution du risque d&#8217;erreur. De plus, nous avons la garantie que l&#8217;ordre d&#8217;exécution des processus n&#8217;a plus aucune importance.<br />
La qualité de transparence référentielle nous aide aussi à implémenter proprement le pattern <a href="http://en.wikipedia.org/wiki/Command-query_separation">Command-Query Separation</a> (CQS), qui conseille de séparer les processus de requêtage des processus d&#8217;écriture. Les nombreux &laquo;&nbsp;lecteurs&nbsp;&raquo; opèrent sur des données immuables, éventuellement disséminées dans un cluster, alors que le processus &laquo;&nbsp;modificateur&nbsp;&raquo; agit sur les données de référence pour leurs ajouter des deltas.</p>
<p>Quelles sont les contreparties? Il devient plus couteux de réaliser de nombreuses modifications aléatoires sur une grande table. Une BDD purement fonctionnelle ne serait donc pas adaptée à la table d&#8217;inventaire d&#8217;Amazon, même si l&#8217;usage de disques SSD permettrait d&#8217;annuler une grande partie de la dégradation de performance.</p>
<p>Remarquez encore une fois qu&#8217;une grande partie de ces bénéfices/contreparties s&#8217;applique telle quelle dans le cas d&#8217;un versioning manuel.</p>
<p><strong>Conclusion</strong></p>
<p>Le choix historique d&#8217;implémenter les BDD à l&#8217;aide de données mutables n&#8217;est plus optimal. Le besoin de protéger les mises à jour dans un environnement concurrent nuit à la scalabilité, et l&#8217;absence d&#8217;historique et de points de retour rend toute manipulation périlleuse.<br />
Une base de données purement fonctionnelle serait intrinsèquement plus sûre, et offrirait une meilleure scalabilité pour de nombreuses applications. En outre, ses besoins seraient tout à fait compatibles avec les bénéfices des disques flash.<br />
Mon pari est qu&#8217;une telle base de données va réellement exister dans les années à venir. Le monde académique en parle depuis les années 80; voir notamment la thèse de Phil Trinder qui avait déjà identifié les conséquences de la transparence référentielle dans les bases de données, puis ouvert la voie vers le requêtage monadique (LINQ) avec ses collègues de l&#8217;université de Glasgow. Il ne lui manquait que du matériel plus performant.<br />
Aujourd&#8217;hui, la startup <a href="http://www.rethinkdb.com">RethinkDB</a> et la base in-memory <a href="http://www.sap.com/hana/index.epx">HANA</a> utilisent déjà une partie de cette technologie et atteignent de belles performances.<br />
En attendant l&#8217;arrivée et la maturation de ces nouveaux outils, il est déjà possible d&#8217;enrichir manuellement nos BDD pour bénéficier, en partie, de leurs avantages.</p>
<p><strong>Bibliographie</strong></p>
<p><a href="http://www-03.ibm.com/ibm/history/exhibits/storage/storage_3330.html">http://www-03.ibm.com/ibm/history/exhibits/storage/storage_3330.html</a> (Histoire du disque dur IBM 3330)<br />
<a href="http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-TN-1997-018.pdf">http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-TN-1997-018.pdf</a> (Génèse du SQL)<br />
<a href="http://www.cs.ox.ac.uk/files/3404/PRG82.pdf">www.cs.ox.ac.uk/files/3404/PRG82.pdf</a>: Phil Trinder &laquo;&nbsp;A functional database&nbsp;&raquo;<br />
<a href="http://www.quora.com/What-would-be-the-main-advantages-of-a-(purely-)-functional-database">http://www.quora.com/What-would-be-the-main-advantages-of-a-(purely-)-functional-database</a><br />
<a href="http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html">http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html</a><br />
<a href="http://research.microsoft.com/~gray/papers/theTransactionConcept.pdf">http://research.microsoft.com/~gray/papers/theTransactionConcept.pdf</a> (Implémentations d&#8217;une transaction)</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=29640" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/outiller-un-audit-de-base-de-donnees/' rel='bookmark' title='Outiller un audit de base de données'>Outiller un audit de base de données</a></li>
<li><a href='http://blog.octo.com/industrialisation-des-developpements-automatisez-votre-base-de-donnees/' rel='bookmark' title='Industrialisation des développements : automatisez votre base de données'>Industrialisation des développements : automatisez votre base de données</a></li>
<li><a href='http://blog.octo.com/des-alternatives-aux-bases-de-donnees-relationnelles%e2%80%a6/' rel='bookmark' title='Des alternatives aux bases de données relationnelles…'>Des alternatives aux bases de données relationnelles…</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/une-base-de-donnees-purement-fonctionnelle-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Vidéo du petit-déjeuner NoSQL : &#171;&#160;l’Extreme Transaction Processing&#160;&#187; devient une réalité</title>
		<link>http://blog.octo.com/video-du-petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=video-du-petit-dejeuner-nosql-l%25e2%2580%2599extreme-transaction-processing-devient-une-realite</link>
		<comments>http://blog.octo.com/video-du-petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 14:14:17 +0000</pubDate>
		<dc:creator>Lina Benhalouche</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[xtp]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=28551</guid>
		<description><![CDATA[Jeudi 15 décembre, OCTO organisait un petit-déjeuner NoSQL : &#171;&#160;l’Extreme Transaction Processing, devient une réalité&#160;&#187;. Aujourd’hui, la multiplication des systèmes connectés à Internet (smartphone, tablette, TV connectée, véhicule connecté) et l’émergence des nouveaux flux de données issus notamment du web social (Facebook commerce, mobile-to-mobile, etc) vont pousser un peu plus les Systèmes d’Information vers l’Extreme Transaction [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite-2/' rel='bookmark' title='Petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité'>Petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité</a></li>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-%c2%ab-comment-batir-votre-cloud-%c2%bb-organise-par-octo-technology/' rel='bookmark' title='Vidéo du petit-déjeuner « Comment bâtir votre Cloud ? » organisé par OCTO Technology'>Vidéo du petit-déjeuner « Comment bâtir votre Cloud ? » organisé par OCTO Technology</a></li>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-mapreduce-la-revolution-dans-lanalyse-des-bigdata-organise-par-octo/' rel='bookmark' title='Vidéo du petit-déjeuner &laquo;&nbsp;MapReduce -La révolution dans l&#8217;analyse des BigData&nbsp;&raquo; organisé par OCTO'>Vidéo du petit-déjeuner &laquo;&nbsp;MapReduce -La révolution dans l&#8217;analyse des BigData&nbsp;&raquo; organisé par OCTO</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fvideo-du-petit-dejeuner-nosql-l%2525e2%252580%252599extreme-transaction-processing-devient-une-realite%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Vid%C3%A9o%20du%20petit-d%C3%A9jeuner%20NoSQL%20%3A%20%5C%22l%E2%80%99Extreme%20Transaction%20Processing%5C%22%20devient%20une%20r%C3%A9alit%C3%A9%22%20%7D);"></div>
<p>Jeudi 15 décembre, <a title="Site OCTO Technology" href="http://www.octo.com/" target="_blank">OCTO</a> organisait un petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing, devient une réalité&nbsp;&raquo;.</p>
<p>Aujourd’hui, la multiplication des <strong>systèmes connectés à Internet </strong>(smartphone, tablette, TV connectée, véhicule connecté) et l’<strong>émergence des nouveaux flux de données</strong> issus notamment du web social (Facebook commerce, mobile-to-mobile, etc) vont pousser un peu plus les Systèmes d’Information vers l’<strong>Extreme Transaction Processing</strong> (XTP).</p>
<p><em>(Pour plus d&#8217;informations sur le contenu, veuillez cliquer <a href="http://blog.octo.com/petit-dejeuner-nosql-l%E2%80%99extreme-transaction-processing-devient-une-realite-2/">ici</a>)</em></p>
<p>Grâce à la vidéo de l’évènement disponible sur You Tube, vous pouvez découvrir les divers points abordés lors de ce Petit-Déjeuner, à savoir :</p>
<ul>
<li>les concepts et les opportunités métiers autour de l’&nbsp;&raquo;<strong>Extreme Transaction Processing</strong>&laquo;&nbsp;</li>
<li>les enjeux d’<strong>architecture</strong> et d’<strong>exploitation</strong></li>
<li>les fonctionnalités et l&#8217;implémentation faite par les solutions VMware Gemfire et SQLFire</li>
</ul>
<p>Pour tout autre renseignement, contactez nous sur : <a href="mailto:contact@octo.com">contact@octo.com</a></p>
<address> </address>
<address>Cliquez sur l’image pour lancer la vidéo</address>
<address><a href="http://www.youtube.com/watch?feature=player_detailpage&amp;v=6vxg-3sm2OE" target="_blank"><img class="aligncenter size-full wp-image-28570" title="Petit-déjeuner NoSQL" src="http://blog.octo.com/wp-content/uploads/2011/12/Petit-déjeuner-NoSQL.png" alt="" width="504" height="315" /></a></address>
<address> </address>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=28551" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite-2/' rel='bookmark' title='Petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité'>Petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité</a></li>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-%c2%ab-comment-batir-votre-cloud-%c2%bb-organise-par-octo-technology/' rel='bookmark' title='Vidéo du petit-déjeuner « Comment bâtir votre Cloud ? » organisé par OCTO Technology'>Vidéo du petit-déjeuner « Comment bâtir votre Cloud ? » organisé par OCTO Technology</a></li>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-mapreduce-la-revolution-dans-lanalyse-des-bigdata-organise-par-octo/' rel='bookmark' title='Vidéo du petit-déjeuner &laquo;&nbsp;MapReduce -La révolution dans l&#8217;analyse des BigData&nbsp;&raquo; organisé par OCTO'>Vidéo du petit-déjeuner &laquo;&nbsp;MapReduce -La révolution dans l&#8217;analyse des BigData&nbsp;&raquo; organisé par OCTO</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/video-du-petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La crise économique, une opportunité à ne pas rater !</title>
		<link>http://blog.octo.com/la-crise-economique-une-opportunite-a-ne-pas-rater/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=la-crise-economique-une-opportunite-a-ne-pas-rater</link>
		<comments>http://blog.octo.com/la-crise-economique-une-opportunite-a-ne-pas-rater/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 09:35:59 +0000</pubDate>
		<dc:creator>Julien Cabot</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Brèves de consultants]]></category>
		<category><![CDATA[Général -- NE PAS UTILISER CETTE CATEGORIE]]></category>
		<category><![CDATA[bigdata]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=28293</guid>
		<description><![CDATA[La crise économique, une opportunité à ne pas rater ! L’actualité financière et les perspectives économiques mettent sous pression les budgets des DSI. Les coups de rabot budgétaires ont le mérite de mettre en évidence les sujets perçus comme les plus importants et urgents. Arbitrer entre maintenir à flot l’activité métier ou la transformer est [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/la-meilleure-facon-de-rater-son-projet-grace-a-maven2/' rel='bookmark' title='La meilleure façon de rater son projet grâce à Maven2'>La meilleure façon de rater son projet grâce à Maven2</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fla-crise-economique-une-opportunite-a-ne-pas-rater%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fuw5a3u%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22La%20crise%20%C3%A9conomique%2C%20une%20opportunit%C3%A9%20%C3%A0%20ne%20pas%20rater%20%21%22%20%7D);"></div>
<p><strong>La crise économique, une opportunité à ne pas rater !</strong><br />
L’actualité financière et les perspectives économiques mettent sous pression les budgets des DSI. Les coups de rabot budgétaires ont le mérite de mettre en évidence les sujets perçus comme les plus importants et urgents.<br />
Arbitrer entre maintenir à flot l’activité métier ou la transformer est un choix difficile pour chaque Direction : « run the business or change the business » ? Les investissements SI sont soumis également à ce dilemme.<br />
Néanmoins, les entreprises qui sauront mettre à profit cette période troublée pour se transformer sauront en bénéficier plus tôt. Alors que celles, qui ne le feront pas, n’auront pas eu le temps de le faire avant la prochaine crise, qui les paralysera à nouveau.<br />
Dans une logique de recentrage des investissements SI, la question est donc de bien identifier les sujets qui permettent d’obtenir une réduction significative des coûts opérationnels et de rentabiliser à court terme la transformation des activités. Il faut bien l’admettre, cet exercice nécessite une bonne dose de créativité et d’innovation.<br />
<span id="more-28293"></span></p>
<p><strong>En période de crise, faut-il ignorer les innovations technologiques ?</strong><br />
La question n’est pas tant la technologie, mais plutôt si les signaux de changement concernent la technologie. L’année 2012 sera-t-elle technologique ? Nous en sommes convaincus en considérant les évolutions suivantes :<br />
• <strong>L’émergence du « big data »</strong>. Le buzzword BigData, qui existe depuis 10 ans, prend une forme réelle aujourd’hui dans les télécommunications, la banque et le commerce en ligne pour exploiter les immenses quantités de données clients (tickets de communication, opérations bancaires, parcours internet, etc.) pour mieux les adresser.<br />
• L’émergence des <strong>nouveaux canaux – Smartphone et Tablette &#8211; de distribution</strong> et de relation client, qui passent du statut d’outils de communication d’entreprise à celui de canal de distribution et de relation client, à l’instar des sites Internet il y a 10 ans. Les investissements sur ces canaux vont devoir se pérenniser et les applications mobiles devront s’inscrire durablement dans les stratégies multicanales des entreprises.<br />
• L’<strong>analyse et la simulation</strong> deviennent une réponse nécessaire pour faire face aux bouleversements des contextes économiques et financiers. Mes marges sont-elles toujours positives en cas d’une augmentation des taux de financement du Besoin en Fonds de Roulement ?<br />
Ces 3 évolutions majeures entrainent avec elles des défis technologiques importants, qui nécessiteront toute l’attention des meilleurs talents de la DSI.<br />
Le management des SI ne pourra plus se résumer à un alignement sur les processus métiers. Il devra reconnecter l’innovation technologique et ses opportunités aux enjeux et aux perspectives business. Et ça, c’est une bonne nouvelle !<br />
La maitrise des usages et des opportunités technologiques appliquées au business deviendra la clef qui permettra de faire la différence en sortie de crise ou avant le commencement d’une nouvelle.</p>
<p><strong>Sur quels sujets technologiques investir ?</strong><br />
Les sujets technologiques sont nombreux. Il convient d’aborder la réflexion sur l’usage métier avant de se lancer dans une veille « à tout-va ». A notre avis, les sujets suivants seront incontournables :<br />
• L’<strong>écosystème NoSQL</strong> qui sert de fondation au Big Data : batch distribué Hadoop, bases de données spécialisées (contenu, graph, clef/valeur, multidimensionnelle, grille), traitement de flux d’évènements (CEP)<br />
• La <strong>convergence entre grille de données et grille de calculs</strong>, qui fournit une nouvelle génération de serveurs d’applications capables de supporter les systèmes mutualisés de très grande taille<br />
• La <strong>programmation parallèle</strong> pour tirer profit des évolutions matérielles des multi-core, GPU et grid computing et rendre abordable les systèmes de calculs et de simulation<br />
• L’<strong>industrialisation des développements Smartphones et Tablettes</strong> pour iOS, Android, Windows Phone et Blackberry tout en alliant l’excellence de l’expérience utilisateur à la pérennisation des investissements sur des plateformes techniques encore en pleine mutation<br />
• La multiplication des <strong>connexions des objets physiques à l’Internet</strong> (smartphone, tablette, table, TV, véhicule, …) va permettre de suivre et de faire interagir le monde de l’information avec celui des actifs physiques, sans intermédiaire humain.<br />
• L’<strong>évolution des infrastructures Cloud</strong>, qui devront renforcer leurs solutions permettant l’intégration entre « SI Cloudifié » et SI existant et le durcissement des systèmes de sécurité applicative au fur et à mesure du déploiement de nouveaux services complexes.<br />
• L’<strong>hégémonie de HTML5</strong> sur les technologies IHM et l’impérative nécessité de <strong>maitriser industriellement les technologies Javascript</strong></p>
<p><strong>La contrainte : aller vite</strong><br />
Indépendamment des sujets choisis, la pression budgétaire augmente celle sur les délais d’obtention de résultats rapides. Il devient donc impératif d’<strong>être efficace dans l’identification des usages sectoriels et la maitrise des nouvelles technologies</strong>.<br />
La R&amp;D OCTO est orientée dans ce sens, en structurant transversalement l’analyse des opportunités technologiques et l’identification des usages dans les secteurs : Banque, Assurance, Télécoms, Media, Internet, Energie, Distribution et Services.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=28293" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/la-meilleure-facon-de-rater-son-projet-grace-a-maven2/' rel='bookmark' title='La meilleure façon de rater son projet grâce à Maven2'>La meilleure façon de rater son projet grâce à Maven2</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/la-crise-economique-une-opportunite-a-ne-pas-rater/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Petit-déjeuner NoSQL : &#171;&#160;l’Extreme Transaction Processing&#160;&#187; devient une réalité</title>
		<link>http://blog.octo.com/petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=petit-dejeuner-nosql-l%25e2%2580%2599extreme-transaction-processing-devient-une-realite-2</link>
		<comments>http://blog.octo.com/petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite-2/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 13:03:16 +0000</pubDate>
		<dc:creator>Lina Benhalouche</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Petit-Déjeuner OCTO]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=28097</guid>
		<description><![CDATA[OCTO organise le jeudi 15 décembre à partir de 8h45 un petit déjeuner gratuit NoSQL : &#171;&#160;l’Extreme Transaction Processing&#160;&#187; devient une réalité,  aux salons Wagram. Pour vous inscrire cliquez ici . Découvrez le descriptif de l’évènement et les intervenants dans ce billet. Les années 2000, avec l’avènement d’Internet comme nouveau canal pour les entreprises, avaient fortement secoué les [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite/' rel='bookmark' title='Vidéo du petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité'>Vidéo du petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité</a></li>
<li><a href='http://blog.octo.com/petit-dejeuner-usabilite-le-29-septembre/' rel='bookmark' title='Petit-déjeuner usabilité, le 29 septembre'>Petit-déjeuner usabilité, le 29 septembre</a></li>
<li><a href='http://blog.octo.com/cr-du-petit-dejeuner-organise-par-octo-et-quartet-fs-lanalyse-decisionnelle-en-temps-reel-convergence-entre-big-data-et-complex-event-processing/' rel='bookmark' title='CR du petit-déjeuner organisé par OCTO et Quartet FS « L’analyse décisionnelle en temps réel Convergence entre Big Data et Complex Event Processing »'>CR du petit-déjeuner organisé par OCTO et Quartet FS « L’analyse décisionnelle en temps réel Convergence entre Big Data et Complex Event Processing »</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fpetit-dejeuner-nosql-l%2525e2%252580%252599extreme-transaction-processing-devient-une-realite-2%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Petit-d%C3%A9jeuner%20NoSQL%20%3A%20%5C%22l%E2%80%99Extreme%20Transaction%20Processing%5C%22%20devient%20une%20r%C3%A9alit%C3%A9%22%20%7D);"></div>
<h3 style="text-align: center;"><strong><a href="http://blog.octo.com/wp-content/uploads/2011/11/Nosql.png"><img class="aligncenter size-full wp-image-28112" title="Nosql" src="http://blog.octo.com/wp-content/uploads/2011/11/Nosql.png" alt="" width="485" height="171" /></a><br />
</strong></h3>
<p>OCTO organise le jeudi 15 décembre à partir de 8h45 un petit déjeuner gratuit NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité,  aux salons Wagram.</p>
<p>Pour vous inscrire <a href="http://www.octo.com/NoSQL.73/Evenements">cliquez ici </a>. Découvrez le descriptif de l’évènement et les intervenants dans ce billet.</p>
<p>Les années 2000, avec l’avènement d’Internet comme nouveau canal pour les entreprises, avaient fortement secoué les Systèmes d’Information et les serveurs d&#8217;applications avaient permis de faire face aux enjeux d&#8217;ouverture et d&#8217;augmentation de traffic sur les systèmes (Transaction Processing).</p>
<p>Aujourd’hui, la multiplication des <strong>systèmes connectés à Internet </strong>(smartphone, tablette, TV connectée, véhicule connecté) et l’<strong>émergence des nouveaux flux de données</strong>issus notamment du web social (Facebook commerce, mobile-to-mobile, etc) vont pousser un peu plus les Systèmes d’Information vers l’<strong>Extreme Transaction Processing</strong> (XTP).</p>
<p>Les technologies XTP (généralement classées sous les acronymes &laquo;&nbsp;noSQL&nbsp;&raquo;, &laquo;&nbsp;Data Grid&nbsp;&raquo;) existent et même si elles étaient jusqu’alors réservées à des secteurs de niche (Marchés financiers, Défense, Industrie du web), l’évolution des architectures techniques permet aujourd’hui de mettre en place ces solutions transactionnelles hautement performantes et abordables dans des secteurs comme la banque, l’assurance, les médias, les télécommunications et le e-commerce. Les bases de données relationnelles se font challenger par ces nouvelles solutions et technologies tant sur le rapport coût/puissance que sur leur simple pertinence technologique.</p>
<p>En qualité d’architectes de Systèmes d’Information, OCTO présentera les <strong>enjeux métiers</strong> et <strong>principes d&#8217;architecture technique</strong> nécessaires à l’Extreme Transaction Processing afin de vous donner une vision claire des principaux enjeux, des compromis nécessaires et du positionnement des solutions du marché.</p>
<p><span id="more-28097"></span></p>
<p>En partenariat, les experts de la division <strong>vFabric</strong> de<strong> VMware</strong> vous présenteront des cas concrets d&#8217;usage et de déploiements XTP avec GemFire et SQLFire basés sur plus de 10 ans d&#8217;expérience en production.</p>
<p><strong>A l’issue de ce séminaire, vous aurez découvert :</strong></p>
<ul>
<li>Les concepts et les opportunités métiers autour de l’&nbsp;&raquo;<strong>Extreme Transaction Processing</strong>&laquo;&nbsp;</li>
<li>Les enjeux d’<strong>architecture</strong> et d’<strong>exploitation</strong></li>
<li>Les fonctionnalités et l&#8217;implémentation faite par les solutions VMware Gemfire et SQLFire</li>
</ul>
<p>Ce séminaire s’adresse aux<strong> architectes techniques</strong> et aux <strong>décideurs IT</strong> qui souhaitent faire passer leur entreprise dans une nouvelle décennie en conduisant des projets d&#8217;étude, de déploiement ou de réflexion autour des architectures XTP, à haute volumétrie et faible latence, sans sacrifier la rentabilité de leurs investissements.</p>
<p><strong>Ce petit-déjeuner sera présenté par :</strong></p>
<ul>
<li>Julien CABOT, OCTO, Associé</li>
<li>Olivier MALLASSI, OCTO, Architecte Senior</li>
<li>Alexandre VASSEUR, VMware, Expert vFabric</li>
</ul>
<div>
<h4 style="text-align: center;"><a href="http://www.octo.com/NoSQL.73/Evenements">Cliquez ici pour vous inscrire au petit-déjeuner : NoSQL</a></h4>
</div>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=28097" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/video-du-petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite/' rel='bookmark' title='Vidéo du petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité'>Vidéo du petit-déjeuner NoSQL : &laquo;&nbsp;l’Extreme Transaction Processing&nbsp;&raquo; devient une réalité</a></li>
<li><a href='http://blog.octo.com/petit-dejeuner-usabilite-le-29-septembre/' rel='bookmark' title='Petit-déjeuner usabilité, le 29 septembre'>Petit-déjeuner usabilité, le 29 septembre</a></li>
<li><a href='http://blog.octo.com/cr-du-petit-dejeuner-organise-par-octo-et-quartet-fs-lanalyse-decisionnelle-en-temps-reel-convergence-entre-big-data-et-complex-event-processing/' rel='bookmark' title='CR du petit-déjeuner organisé par OCTO et Quartet FS « L’analyse décisionnelle en temps réel Convergence entre Big Data et Complex Event Processing »'>CR du petit-déjeuner organisé par OCTO et Quartet FS « L’analyse décisionnelle en temps réel Convergence entre Big Data et Complex Event Processing »</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/petit-dejeuner-nosql-l%e2%80%99extreme-transaction-processing-devient-une-realite-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GemFire et traitement distribué</title>
		<link>http://blog.octo.com/gemfire-et-traitement-distribue/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=gemfire-et-traitement-distribue</link>
		<comments>http://blog.octo.com/gemfire-et-traitement-distribue/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 07:30:37 +0000</pubDate>
		<dc:creator>Nicolas Colomer</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[big data]]></category>
		<category><![CDATA[Data Grid]]></category>
		<category><![CDATA[Map Reduce]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=26473</guid>
		<description><![CDATA[Les enjeux autour de la donnée sont en train de changer par rapport à ce que l’on connait depuis les SGBDR : volume de plus en plus important, nombre d’utilisateur croissant, accès concurrents et transactionnels intensifs à la fois en lecture et en écriture, haute disponibilité à des niveaux coûts acceptables, coût de licence. Dans [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/transactions-en-grails/' rel='bookmark' title='Transactions et traitement métier en Grails'>Transactions et traitement métier en Grails</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fgemfire-et-traitement-distribue%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FnZJRFs%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22GemFire%20et%20traitement%20distribu%C3%A9%22%20%7D);"></div>
<p>Les enjeux autour de la donnée sont en train de changer par rapport à ce que l’on connait depuis les SGBDR : volume de plus en plus important, nombre d’utilisateur croissant, accès concurrents et transactionnels intensifs à la fois en lecture et en écriture, haute disponibilité à des niveaux coûts acceptables, coût de licence. Dans un tel contexte, les bases de données traditionnelles peuvent  montrer leurs limites.</p>
<p><span id="more-26473"></span></p>
<p>Parmi les différentes réponses à ces enjeux que l’ont a vu émerger ces dernières années, deux d’entre elles se sont révélées particulièrement efficaces :</p>
<ul>
<li>L’utilisation d’architectures distribuées permet de répartir non seulement la charge mais aussi les données sur plusieurs fournisseurs de données. Les éditeurs de SGBD proposent d’ors et déjà des versions clusterisées de leurs solutions (<a href="http://www.oracle.com/fr/products/database/options/rac/index.html">Oracle RAC</a>, <a href="http://www.mysql.fr/products/cluster/">MySQL Cluster</a>, <a href="http://pgfoundry.org/projects/pgcluster/">PGCluster</a>, SQL Server cluster) et de nouvelles solutions « scalable-ready » apparaissent, portées par la mouvance NoSQL (<a href="http://cassandra.apache.org/">Cassandra</a>, <a href="http://hbase.apache.org/">HBase</a>, <a href="http://www.mongodb.org/">MongoDB</a>, <a href="http://couchdb.apache.org/">CouchDB</a>).</li>
<li>L’utilisation de cache, pour chaque fournisseur de données, permet d’accélérer drastiquement les performances d’accès aux données. Certaines solutions appelées « memcache » ont été spécifiquement conçues pour proposer de tels systèmes. On peut citer par exemple <a href="http://redis.io/">Redis</a> ou encore <a href="http://memcached.org/">Memcached</a>. Ces caches restent (encore bien souvent) limités à des architectures orientées « lecture ».</li>
</ul>
<p>Les data grids ont challengé les SGBDR en réunissant les deux précédentes réponses : du partitionnement et du stockage mémoire (suivant les configurations choisies). Les acteurs sont multiples : Oracle, Gigaspaces mais également GemStone (VMWare)</p>
<h1>1. GemFire, kesako ?</h1>
<p>GemFire est la solution de cache distribué éditée par GemStone Systems, récemment acquis par VMWare. Encore appelé « VMware vFabric GemFire », GemFire est un composant de l’écosystème vFabric de VMware.</p>
<p>Cette solution propose, en plus de son framework, des mécanismes avancés de partitionnement (« <a href="http://en.wikipedia.org/wiki/Shard_%28database_architecture%29">sharding </a>»), de persistance et de réplication. Ecrit en Java, GemFire peut fonctionner sur une JVM 32 ou 64 bits, c’est à dire sur n’importe quel OS compatible. Les clients peuvent être écrits à la fois en C++, C# ou Java grâce aux API fournies.</p>
<p>GemFire est un cache orienté-objet qui offre les services d’une base de donnée traditionnelle : OQL (une extension orientée objet du langage SQL), transactions (implémente l’interface JTA), cohérence des données (selon le paramétrage choisi), persistance sur disque (via les mécanismes de write behind ou write through), ou encore tolérance aux pannes.</p>
<p>En plus de ces fonctionnalités classiques, on retrouve également des mécanismes plus spécifiques comme le « continuous querying » permettant d’être notifié lorsque le résultat d’une requête a changé, ou le « function execution », permettant de distribuer un traitement au sein du clustrer GemFire. Ce sujet sera l’objet de la deuxième partie de cet article</p>
<h2>1.1. Architecture de Gemfire</h2>
<p>Un système distribué GemFire se compose de <strong>membres</strong>, des processus Java connectés les uns aux autres au travers d’un réseau. Chaque membre embarque un cache, fonctionnant soit en mode stockage (<em>« data host »</em>) soit en mode proxy (« <em>data accessor »</em>). Dans le premier cas, des données peuvent être écrite localement puis propagées ; dans l’autre cas, le cache agira comme une simple passerelle vers les données  distantes contenues dans la grille de données.</p>
<p>On distingue ainsi deux types de membre :</p>
<ul>
<li>Le <strong>client</strong>, généralement une application embarquant un cache GemFire et connecté au système via une API.</li>
<li>Le  <strong>serveur</strong> (ou « cacheserver »),  un <strong>membre</strong> spécialisé dans le stockage de données qui s’exécute de façon autonome dans une JVM dédiée.</li>
</ul>
<p>Ces membres se découvrent entre eux de deux façons :</p>
<ul>
<li>Par l&#8217;intermédiaire de <strong>Locators</strong>. Ces sont des membres spécialisés qui maintiennent à jour une liste des membres composant l’architecture distribuée.</li>
<li>Par <strong>multicast</strong>. Chaque nouveau membre manifeste sa présence en émettant sur une IP et un port préalablement défini.</li>
</ul>
<p style="text-align: center;"><a href="http://blog.octo.com/wp-content/uploads/2011/10/1.png"><img class="size-medium wp-image-26474 aligncenter" title="Exemple d'architecture distribuée avec GemFire" src="http://blog.octo.com/wp-content/uploads/2011/10/1-300x182.png" alt="" width="300" height="182" /></a></p>
<p>Dans le schéma précédent, on observe que le système distribué peut adopter plusieurs topologies :</p>
<ul>
<li><a href="http://www.gemstone.com/docs/6.5.0/product/docs/html/Manuals/DevelopersGuide/images/Introduction.2.3.1.png">Peer-to-peer </a>: les données sont partagées entre plusieurs clients (liens bleus).</li>
<li><a href="http://www.gemstone.com/docs/6.5.0/product/docs/html/Manuals/DevelopersGuide/images/Introduction.2.3.2.png">Client/serveur</a> : les données sont partagées au sein d’un cluster dédié de serveurs sur lequel peuvent se connecter les clients (liens verts et gris).</li>
<li><a href="http://www.gemstone.com/docs/6.5.0/product/docs/html/Manuals/DevelopersGuide/images/Introduction.2.3.3.png">Multi-site </a>: plusieurs systèmes distribués sont reliés entre eux  via un ou plusieurs membres déclarés en tant que « gateway hubs » (non représenté).</li>
</ul>
<p>Pour synchroniser les différents nœuds, GemFire propose une API de propagation par delta permettant de réduire les échanges sur le réseau, surtout dans le cas de régions fortement répliquées.</p>
<h2>1.2. La sémantique</h2>
<p>Dans GemFire, le concept principal est celui de <strong>région</strong>. Une région, encore appelé « data set », est un groupe logique dans lequel sont stockées les données.</p>
<p>Chaque région possède sa propre configuration (modèle de données, type de partitionnement, présence de réplication, nature de la persistance, gestion des événements). Cette configuration devra être déclarée à l’identique dans chacun des membres utilisant la région. Elle se fait via un descripteur XML ou programmatiquement, au travers de l’API GemFire.</p>
<p>Toute région implémente la bien-connue interface java.util.Map : la manipuler ne devrait pas poser de problème ! Les données y sont donc stockées sous forme de clef/valeur. Clefs et valeurs prennent toutes deux la forme d’un objet Java, toutefois, la clef sera le plus souvent une simple chaine de caractères.</p>
<p>On dénombre 4 types de régions :</p>
<ul>
<li><strong>Locale</strong>, la région n’est accessible que par le membre qui l’a déclaré et ne sera donc partagé avec aucun autre membre.</li>
<li><strong>Distribuée</strong>, chaque membre stock localement les données qu’il créé, mais les partages avec les autres membres du système.</li>
<li><strong>Répliquée</strong>, chacun des membres du système détient une copie complète de toutes les données de la région.</li>
<li><strong>Partitionnée</strong>, les données sont réparties au travers des différents membres de la région, soit équitablement, soit selon des règles de partitionnement préalablement définies. Il est de plus possible de répliquer ces données (« redundant copies ») sur un ou plusieurs membres, afin de garantir leur haute disponibilité. Ainsi chaque membre est responsable d’une partition et héberge n réplicas d’autres partitions.</li>
</ul>
<p>GemFire offre 3 modes de distribution (ou « scope ») des données permettant d’assurer différents niveaux de cohérence :</p>
<ul>
<li><strong>Distributed-no-ack</strong> : aucune contrainte n’est imposée lors de la propagation d’opérations. Ce niveau offre les meilleures performances, mais est sujet aux problèmes de concurrence.</li>
<li><strong>Distributed-ack</strong> : les opérations distribuées sont validées par un système d’acquittement. Ce niveau est moins exposé aux problèmes de concurrence</li>
<li><strong>Global </strong>: les entrées d’une région sont automatiquement verrouillées lorsqu’elles sont modifiées. C’est le seul scope permettant d’assurer une cohérence forte des données, mais c’est aussi le moins performant.</li>
</ul>
<h1>2. Distribuer un traitement</h1>
<p>Le requêtage des données d’une région se fait via OQL. Ce langage répond à des besoins standard en autorisant l’utilisation de clauses SQL bien-connues telles que SELECT, FROM ou WHERE. Il est également possible de réaliser des jointures entre régions et des indexes.</p>
<p>Toutefois, les requêtes OQL sont soumises à certaines limitations qui dépendent principalement du type de région sur lequel on les exécute. Ces limitations concernent entre autre la cohérence des résultats dans le cas de régions répliquées ou distribuées. En effet, pour ces deux types de région, les requêtes sont effectuées sur les données contenues dans le cache local, qui peut, dans certains cas (race conditions, selon la stratégie de propagation), ne pas être cohérentes à un instant donné.</p>
<p>Lorsque l’on aborde la question du traitement au sein d’une architecture distribuée, on entend souvent parler de MapReduce. Le concept est simple : au lieu de rapatrier les données sur un nœud pour traitement, c’est la fonction réalisant ce traitement qui est envoyé sur chacun des nœuds, c’est à dire au plus proche de la donnée. Ceci offre l’avantage de paralléliser l’exécution de la fonction sur différents nœuds tout en diminuant les échanges au niveau du réseau.</p>
<p>Le « function execution service » fourni par GemFire, bien qu’assez éloigné de MapReduce, s’inspire de ce mécanisme. En voici les détails.</p>
<h2>2.1. Mécanismes mis en jeu</h2>
<p>Toute fonction distribuée doit être préalablement déclarée et déployée sur chaque membre d’une région partitionnée lors de son déploiement (descripteur + classpath). Cela implique que ces fonctions aient été préalablement codées en Java, compilées puis éventuellement packagées.</p>
<p>Lorsqu’un client déclenche l’exécution d’une fonction distribuée (action non bloquante pour le client), le serveur (<em>data host</em>) auquel il est connecté va notifier tous les autres serveurs du cluster, contenant localement une partie des données à traiter, d’engager l’exécution de ladite fonction.</p>
<p>Dans le cas ou la fonction retourne des résultats, les différents serveurs vont les soumettre à un collecteur de résultat contenu dans le serveur directement connecté au client. Ce collecteur accumule les résultats jusqu’à ce que chaque serveur ait notifié l’envoie du dernier résultat.</p>
<p>Le client peut alors les récupérer :</p>
<ul>
<li>de manière bloquante : attente de la totalité des résultats, possibilité de spécifier un timeout.</li>
<li>de manière non bloquante : le résultat récupéré par le client est alors potentiellement incomplet.</li>
</ul>
<p>La documentation ne spécifie aucun mécanisme de callback permettant de notifier de manière asynchrone la disponibilité d’un résultat complet.</p>
<p>Ces différentes étapes se résument dans le schéma suivant :</p>
<p style="text-align: center;"><a href="http://blog.octo.com/wp-content/uploads/2011/10/2.png"><img class="size-medium wp-image-26475 aligncenter" title="Fonction distribuée dans GemFire" src="http://blog.octo.com/wp-content/uploads/2011/10/2-300x211.png" alt="" width="300" height="211" /></a></p>
<p><strong>Remarque </strong>: le client peut restreindre l’exécution à un, une partie ou tous les membres d’une région. Il peut également spécifier directement les clefs qui seront soumise au traitement. Ces possibilités sont très utiles, par exemple lorsqu’a été défini une politique de partitionnement spécifique.</p>
<h2>2.2. Contexte de l’exemple</h2>
<p>Afin d’expérimenter le traitement distribué, nous nous sommes placé dans le contexte d’un service web. Cet exemple entre dans la continuité d’un <a href="../../../../../le-push-web-vu-par-diffusion-partie-2/">POC</a> réalisé en interne chez Octo. Nous avons souhaité calculer à la demande des informations statistiques sur la vitesse de véhicules au travers de données brutes remontées par ces derniers.</p>
<p>L’architecture visée se compose des éléments GemFire suivants :</p>
<ul>
<li>Deux <em>CacheServer</em> et un <em>Locator</em>, déployés sur une machine virtuelle</li>
<li>Une application web JEE, déclenchant l’exécution de la fonction distribuée à la demande d’un utilisateur</li>
</ul>
<h2>2.3. Réalisation de la fonction distribuée</h2>
<p>L’exécution de notre fonction distribuée va nécessiter 4 classes :</p>
<ul>
<li><em>SpeedAverageFunction</em>, représente la fonction à exécuter sur chacun des nœuds du cluster. Cette fonction récupère dans la partition locale toutes les vitesses instantanées pour un véhicule donné. Ces données sont transmises au SpeedAverageCollector via l’objet ResultSender.</li>
<li><em>SpeedAverageCollector</em>, doit collecter les résultats retournés par les différents nœuds du cluster (action 4 dans le schéma précédent).</li>
<li><em>SpeedAverageResult</em>, permet de stocker les résultats prétraités. C’est l’objet qui sera renvoyé par le collecteur au client.</li>
<li><em>GemFireManager</em>, récupère et fournit une instance de la région. Elle permet de déclencher l’exécution de notre fonction distribuée, en spécifiant en argument l’identifiant du véhicule dont la vitesse moyenne doit être calculé.</li>
</ul>
<p>Détaillons tour à tour chacune de ces 4 classes.</p>
<h3>2.3.1. SpeedAverageFunction</h3>
<p>Cette classe contient le traitement a effectuer par chacun des <em>data hosts</em> auxquels elle sera soumise. Toute fonction distribuée doit implémenter les interfaces <em>Function</em> et <em>Declarable</em>, cette dernière interface permettant d’être déclarée au sein d’un descripteur XML (voir la partie déploiement). Ci-après, le code commenté de la classe <em>SpeedAverageFunction</em>.</p>
<pre class="brush:java">import com.gemstone.gemfire.cache.Declarable;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.execute.ResultSender;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.cache.query.TypeMismatchException;
import com.octo.rtf.ws.model.VehicleMessage;

public class SpeedAverageFunction implements Declarable, Function {

	@Override
	public void init(Properties props) {
		// Distributed function name extracted from XML descriptor
		functionName = props.getProperty("name");
	}

	@Override
	public void execute(FunctionContext fc) {
		RegionFunctionContext context = (RegionFunctionContext) fc;
		// Get local region data
		Region localRegion = PartitionRegionHelper.getLocalDataForContext(context);
		// Get the result collector
		ResultSender resultSender = context.getResultSender();
		// Retrieve arguments
		String[] args = (String[]) context.getArguments();

		try {
			// Execute the query
			SelectResults queryResults = localRegion.query(formQuery(args));
			// Extract the results
			Map results = queryRouteAverage(queryResults);
			for (String key : results.keySet()) {
				Integer[] data = results.get(key);
				// Send each result to the collector
				resultSender.sendResult(new Object[] {key, data[0], data[1]});
			}
			resultSender.lastResult(null);
		} catch (
	}

	@Override
	public boolean hasResult() {
		// Does the function return results ?
		return true;
	}

	@Override
	public boolean isHA() {
		// Is the high availability option set ?
		return false;
	}

	@Override
	public boolean optimizeForWrite() {
		// Does the function write results on region ?
		return false;
	}
}</pre>
<h3>2.3.2. SpeedAverageCollector</h3>
<p>Cette classe implémente l’interface <em>ResultCollector&lt;T extends Serializable,S extends Serializable&gt;</em>. T correspond à l’objet en entrée, c’est à dire retourné par les <em>data hosts</em> lorsqu’ils récupèrent des données (dans le cas de notre SpeedAverageCollector, un tableau d’objet), et S correspond à l’objet en sortie, c’est à dire retourné au client (ici, un objet SpeedAverageResult).</p>
<p>Ci-après, le code commenté de la classe <em>SpeedAverageCollector</em>.</p>
<pre class="brush:java">import com.gemstone.gemfire.cache.execute.FunctionException;
import com.gemstone.gemfire.cache.execute.ResultCollector;
import com.gemstone.gemfire.distributed.DistributedMember;

public class SpeedAverageCollector implements ResultCollector  {

	SpeedAverageResult sar = new SpeedAverageResult();

	public SpeedAverageCollector() {}

	@Override
	public void addResult(DistributedMember memberID,
			Object[] resultOfSingleExecution) {
		// Executed when a member return a result
		if (resultOfSingleExecution == null) return;
		String type = (String) resultOfSingleExecution[0];
		int value = (Integer) resultOfSingleExecution[1];
		int weight = (Integer) resultOfSingleExecution[2];
		sar.addResult(type, value, weight);
	}

	@Override
	public void clearResults() {
		// When the function is reexucted
		sar = new SpeedAverageResult();
	}

	@Override
	public void endResults() {
		// When a member sends its last result
	}

	@Override
	public SpeedAverageResult getResult() throws FunctionException {
		// Return the result (blocks until the last result is sent)
		return sar;
	}

	@Override
	public SpeedAverageResult getResult(long timeout, TimeUnit unit)
			throws FunctionException, InterruptedException {
		// Returns the result (blocks until timeout)
		return getResult();
	}
}</pre>
<h3>2.3.3. SpeedAverageResult</h3>
<p>Cette classe va contenir l’ensemble des résultats et leurs accesseurs. Elle doit implémenter l’interface <em>Serializable</em> afin de pouvoir transférée aux <em>data hosts</em> via le réseau. Ci-après, le code commenté de la classe <em>SpeedAverageResult</em>.</p>
<pre class="brush:java">public class SpeedAverageResult implements Serializable {

	private Map results;

	public SpeedAverageResult() {
		results = new HashMap();
	}

	public void addResult(String type, int value, int weight) {
		if (!results.containsKey(type)) {
			results.put(type, new Integer[] {value, weight});
		} else {
			Integer[] data = results.get(type);
			data[0] += value;
			data[1] += weight;
		}
	}

	public Double getAverage() {
		int sum = 0, num = 0;
		for (String type : results.keySet()) {
			Integer[] data = results.get(type);
			sum += data[0];
			num += data[1];
		}
		if (num == 0) return new Double(0);
		else return (double) (sum / num);
	}

	public Map getAverageByHighway() {
		Map result = new HashMap();
		for (String type : results.keySet()) {
			result.put(type, getAverageForHighway(type));
		}
		return result;
	}

	public Double getAverageForHighway(String type) {
		Integer[] data = results.get(type);
		return (double) (data[0] / data[1]);
	}
}</pre>
<h3>2.3.4. GemFireManager</h3>
<p>Cette classe va permettre de se connecter en tant que client au système distribué GemFire. Elle va récupérer et fournir une instance de la région qui permettra de stocker les messages de nos véhicules connectés. La méthode <em>getSpeedAverageFromVin</em>() permettra de déclencher l’exécution de la fonction distribuée sur notre région. Ci-après, le code de la classe GemFireManager</p>
<pre class="brush:java">import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.octo.rtf.ws.model.VehicleMessage;

public class GemFireManager {

	private static final String LOCATOR_IP = "192.168.56.101";
	private static final int LOCATOR_PORT = 55221;
	private static final String REGION_NAME = "VehicleMessageRegion";
	private static final String FUNCTION_SPEEDAVERAGE = "SpeedAverage";

	private static ClientCache cache;
	private static Region region;

	public GemFireManager() {
		// Create a local client cache
		cache = new ClientCacheFactory()
			.addPoolLocator(LOCATOR_IP, LOCATOR_PORT)
			.set("log-level", "error").create();
		// Get the region
		region = cache.createClientRegionFactory(ClientRegionShortcut.PROXY)
			.create(REGION_NAME);
	}

	public SpeedAverageResult getSpeedAverageFromVin(String vin) {
		Execution execution = FunctionService
			.onRegion(region)
			.withCollector(new SpeedAverageCollector())
			.withArgs(new String[] {vin});
		SpeedAverageCollector collector = (SpeedAverageCollector) execution
			.execute(FUNCTION_SPEEDAVERAGE, true, false, false);
		return collector.getResult();
	}
}</pre>
<h2>2.4. Configuration et déploiement des composants</h2>
<h3>2.4.1. Définissons la région</h3>
<p>La région que nous allons créer ici devra stocker l’ensemble des messages remontés par les véhicules. Ces messages contiennent des données brutes, parmi lesquels un timestamp, la vitesse instantanée et le type de route emprunté.</p>
<p>Pour définir cette région, utilisons un descripteur XML :</p>
<pre class="brush:xml">&lt;?xml version=<em>"1.0"</em> encoding=<em>"UTF-8"</em>?&gt;
&lt;!DOCTYPE cache PUBLIC
"-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
"http://www.gemstone.com/dtd/cache6_5.dtd"&gt;
&lt;cache&gt;
	&lt;region name=<em>"VehicleMessageRegion"</em> refid=<em>"PARTITION"</em>&gt;
		&lt;region-attributes&gt;
			&lt;value-constraint&gt;com.octo.rtf.ws.model.VehicleMessage&lt;/value-constraint&gt;
		&lt;/region-attributes&gt;
	&lt;/region&gt;
	&lt;function-service&gt;
		&lt;function&gt;
			&lt;class-name&gt;com.octo.rtf.ws.gemfire.SpeedAverageFunction&lt;/class-name&gt;
			&lt;parameter name="name"&gt;&lt;string&gt;SpeedAverage&lt;/string&gt;&lt;/parameter&gt;
		&lt;/function&gt;
	&lt;/function-service&gt;
&lt;/cache&gt;</pre>
<p>Le descripteur est plutôt explicite : nous définissons ici un cache contenant une région partitionnée nommée <em>VehicleMessageRegion</em>, dont la valeur sera un objet <em>VehicleMessage</em>. La clef sera une simple chaine de caractère (non spécifiée donc nature par défaut). Enfin nous spécifions une fonction exécutable au travers de son identifiant « SpeedAverage ».</p>
<h3>2.4.2. Dépendances Java</h3>
<p><em>Locator</em> et <em>CacheServer</em> sont des processus Java indépendants. Afin d’être lancés, déclarons quelques variables d’environnement permettant de régler définitivement le problème des dépendances.</p>
<pre class="brush:text"># VARIABLES GEMFIRE
GF_JAVA=$JAVA_HOME/bin/java; export GF_JAVA
PATH=$PATH:$JAVA_HOME/bin:$GEMFIRE/bin; export PATH
GEMFIRE=/srv/GemFire6514
CLASSPATH=$GEMFIRE/lib/gemfire.jar:$GEMFIRE/lib/antlr.jar:$GEMFIRE/lib/gfSecurityImpl.jar:$CLASSPATH; export CLASSPATH</pre>
<h3>2.4.3. Initialisation du Locator</h3>
<p>Afin de déployer notre système distribué GemFire, choisissons la méthode du locator (par opposition à la méthode multicast). Le locator est un processus à l’écoute d’un port, réalisant la coordination entre les différents membres du système distribué GemFire. Le <em>Locator</em> peut être respectivement lancé et arrêté au travers des commandes suivantes.</p>
<pre class="brush:text">gemfire locator-stop -port=55221 -address=192.168.56.101
gemfire locator-start -port=55221 -address=192.168.56.101</pre>
<h3>2.4.4. Lancement des cacheserver</h3>
<p>Pour fonctionner, un cacheserver a besoin d’un répertoire de travail dans lequel il persistera les données (si l’option est spécifiée) ainsi que les différents logs.</p>
<p>Démarrons deux <em>cacheservers</em> dans deux répertoires distincts.</p>
<pre class="brush:text">mkdir ./server1 ./server2
cacheserver start locators=192.168.56.101[55221] mcast-port=0 cache-xml-file=.. /server.xml -server-bind-address=192.168.56.101 -server-port=0 -dir=./server1
cacheserver start locators=192.168.56.101[55221] mcast-port=0 cache-xml-file=../server.xml -server-bind-address=192.168.56.101 -server-port=0 -dir=./server2</pre>
<p>Pour stopper ces deux cacheserver, il suffit d’utiliser les commandes suivantes</p>
<pre class="brush:text">cacheserver stop -dir=./server1
cacheserver stop -dir=./server2</pre>
<p>Le système est maintenant prêt à opérer. Pour voir un exemple du résultat, n’hésitez pas à consulter le <a href="../../../../../le-push-web-vu-par-diffusion-partie-2/">screencast</a> disponible dans la deuxième partie de l’article concernant le push web.</p>
<h1>3. Conclusion</h1>
<p>Nous avons pu constater au travers de cet article que :</p>
<ul>
<li>Les efforts à fournir pour déployer une telle architecture sont loin d’être insurmontables.</li>
<li>L’exécution de fonctions distribuées est particulièrement simple à mettre en œuvre.</li>
</ul>
<p>Les fonctions distribuées ne forment cependant qu’une partie de ce que propose GemFire. Le framework offre également d’autres outils, comme la propagation par deltas pour réduire la charge sur le réseau ou le mécanisme de « Continuous Querying » qui permet d’être notifié sur changement du résultat d’une requête ou de l’état d’une région…</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=26473" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/transactions-en-grails/' rel='bookmark' title='Transactions et traitement métier en Grails'>Transactions et traitement métier en Grails</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/gemfire-et-traitement-distribue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BigData : la fin des architectures basées sur les processus métiers?</title>
		<link>http://blog.octo.com/bigdata-la-fin-des-architectrures-basees-sur-les-processus-metiers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=bigdata-la-fin-des-architectrures-basees-sur-les-processus-metiers</link>
		<comments>http://blog.octo.com/bigdata-la-fin-des-architectrures-basees-sur-les-processus-metiers/#comments</comments>
		<pubDate>Tue, 17 May 2011 08:00:51 +0000</pubDate>
		<dc:creator>Julien Cabot</dc:creator>
				<category><![CDATA[Brèves de consultants]]></category>
		<category><![CDATA[architecture SI]]></category>
		<category><![CDATA[big data]]></category>
		<category><![CDATA[Management du SI]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=22575</guid>
		<description><![CDATA[Le BigData, une nouvelle (r)évolution pour les entreprises? McKinsey a publié récemment un rapport sur l&#8217;avènement du BigData comme nouveau paradigme de compétition entre les entreprises. L&#8217;analyse massive et le développement du capital informationnel (le BigData) deviendrait un nouveau levier pour la productivité, l&#8217;innovation et la croissance. Le rapport met en évidence 5 clefs pour [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/petit-dejeuner-mapreduce-la-revolution-dans-lanalyse-des-bigdata-le-27-septembre/' rel='bookmark' title='Petit-déjeuner MapReduce-La révolution dans l&#8217;analyse des BigData le 27 septembre'>Petit-déjeuner MapReduce-La révolution dans l&#8217;analyse des BigData le 27 septembre</a></li>
<li><a href='http://blog.octo.com/a-quand-de-vraies-architectures-stateless/' rel='bookmark' title='A quand de vraies architectures Stateless?'>A quand de vraies architectures Stateless?</a></li>
<li><a href='http://blog.octo.com/architectures-web/' rel='bookmark' title='Architectures Web : 3 questions à Jean-François Caenen'>Architectures Web : 3 questions à Jean-François Caenen</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fbigdata-la-fin-des-architectrures-basees-sur-les-processus-metiers%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22BigData%20%3A%20la%20fin%20des%20architectures%20bas%C3%A9es%20sur%20les%20processus%20m%C3%A9tiers%3F%22%20%7D);"></div>
<p><strong>Le BigData, une nouvelle (r)évolution pour les entreprises?<br />
</strong></p>
<p>McKinsey a publié récemment un <a href="http://www.mckinsey.com/mgi/publications/big_data/index.asp">rapport sur l&#8217;avènement du BigData</a> comme nouveau paradigme de compétition entre les entreprises.</p>
<p>L&#8217;analyse massive et le développement du capital informationnel (le BigData) deviendrait un nouveau levier pour la productivité, l&#8217;innovation et la croissance.</p>
<p><span id="more-22575"></span>Le rapport met en évidence 5 clefs pour tirer profit du concept de BigData :</p>
<blockquote>
<ul>
<li><strong>Make big data more accessible and timely.</strong> Transparency, enabled by big data, can unlock a great deal of value. In the public sector, increasing access to data across separate departments can sharply reduce search and processing times. In manufacturing, integrating data from R&amp;D, engineering, and manufacturing units to facilitate concurrent engineering can cut time to market.</li>
<li><strong> Use data and experiments to expose variability and raise performance.</strong> As organizations create and store more transactional data in digital form, they can collect more accurate and detailed performance information on everything from product inventories to sick days.</li>
<li><strong>Segment populations to customize.</strong> Big data allow organizations to create ever-narrowing segmentations and to tailor services precisely to meet customer needs. This approach is well known in marketing and risk management but can be revolutionary in areas such as the public sector.</li>
<li><strong>Use automated algorithms to replace and support human decision making.</strong> Sophisticated analytics can substantially improve decision making, minimize risks, and unearth valuable insights that would otherwise remain hidden. Such analytics have applications from tax agencies to retailers.</li>
<li><strong>Innovate with new business models, products, and services.</strong> To improve the development of next-generation offerings and to create innovative after-sales services, manufacturers are leveraging data obtained from the use of products. The emergence of real-time location data has created a new set of location-based mobile services from navigation to people tracking.</li>
</ul>
</blockquote>
<p><strong>Y aura-t-il un impact dans la manière de concevoir les SI?</strong></p>
<p>Les technologies de stockage et de traitement de données sont en train de connaitre probablement une évolution aussi importante que l&#8217;apparition des serveurs d&#8217;applications. Le monde des technologies NoSQL, CEP et BI est en train de vivre sa révolution. Mon point ne porte pas tellement sur l&#8217;émergence de nouvelles technologies challengeant l&#8217;hégémonie des bases de données relationnelles traditionnelles, mais plutôt l&#8217;implication de BigData en matière d&#8217;architecture de SI.</p>
<p><strong>Depuis 20 ans, nous concevons des SI alignées sur les processus métiers des organisations pour permettre l&#8217;amélioration de la productivité des entreprises par l&#8217;automatisation des processus.</strong> Ce même souhait nous a fait aboutir à des systèmes d&#8217;informations segmentés par grandes familles de processus (front, back , support, pilotage, transverse, etc.)</p>
<p>Sans le dire, <strong>BigData nous fait passer d&#8217;une logique de <em>commoditisation des processus métiers</em> à celle de l&#8217;exploitation d&#8217;un actif (mal identifié) de l&#8217;entreprise : l&#8217;Information.</strong></p>
<p>Dans un précédent article, je mettais en lumière la <a href="http://www.asset45.com/2011/05/le-si-actif-ou-commodite-de-lentreprise/"><strong>double position du SI en tant que commodité ET actif</strong></a> de l&#8217;entreprise.<br />
Le BigData met un mot pour qualifier un SI, actif stratégique, capable de faire émerger les nouvelles opportunités business, de tarifier au plus fin sur la base des comportements réels des clients, de casser les asymétries d&#8217;information qui freinent la collaboration entre les entités des organisations,etc.<br />
<strong><br />
Comment pouvons bâtir de tels SI en utilisant des principes d&#8217;architecture qui favorisent le cloisonnement plutôt que le partage de l&#8217;information et qui repose sur la mise en œuvre d&#8217;expression de besoin pré-identifiée?</strong></p>
<p>Un SI qui maximise la valeur de l&#8217;information d&#8217;une entreprise peut-il avoir une architecture cloisonnée entre informations front office et back office? La construction à-côté d&#8217;un SI Décisionnel alimenté par le SI Opérationnel pourra-t-il permettre de réagir suffisamment vite et de prendre des décisions rapidement?</p>
<p><strong>Comment définir un SI qui tire profit des BigData?</strong></p>
<p>L&#8217;article suivant identifie <a href="http://www.asset45.com/2011/05/la-valeur-de-information/">des caractéristiques clefs de l&#8217;information en tant qu&#8217;actif de l&#8217;entreprise</a>.</p>
<p>Un SI BigData devrait donc être</p>
<ul>
<li><strong>Partagé</strong> : Tout le monde accède à la même source d&#8217;information</li>
<li><strong>Utilisé</strong> : Utilisé par tous &#8211; collaborateurs, clients, partenaires, fournisseurs, &#8230;</li>
<li><strong>A date</strong> : La notion de courant/historisé disparaît au profit d&#8217;une notion de date d&#8217;événement, proche de celle de la date de valeur (passée, présente et futur)</li>
<li><strong>Précis</strong> : Toutes les données brutes sont présentes et rattachées aux informations de plus haut niveaux</li>
<li><strong>Comparable/Combinable</strong> : Les informations reposent sur les mêmes données brutes pour pouvoir être comparées et combinées?</li>
<li><strong>Piloté par la valeur</strong> : le traitement de l&#8217;information (par opposition à celui des données) est consommateur en temps et énergie, il convient de choisir ses informations pour ne pas perdre en productivité</li>
<li><strong>Réutilisable</strong> : l&#8217;information doit pouvoir servir de base à une autre</li>
</ul>
<p><strong>Conclusion</strong><br />
Avec le BigData, la forme de nos systèmes d&#8217;information pourrait bien changer. Imaginez le SI d&#8217;une banque avec un immense nuage mondial de données d&#8217;événements de gestion de compte qui permettrait aux front de connaitre le comportement de chaque client, de proposer des produits totalement personnalisés, de décloisonner conseiller agence, banque en ligne, conseiller en patrimoine, etc.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=22575" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/petit-dejeuner-mapreduce-la-revolution-dans-lanalyse-des-bigdata-le-27-septembre/' rel='bookmark' title='Petit-déjeuner MapReduce-La révolution dans l&#8217;analyse des BigData le 27 septembre'>Petit-déjeuner MapReduce-La révolution dans l&#8217;analyse des BigData le 27 septembre</a></li>
<li><a href='http://blog.octo.com/a-quand-de-vraies-architectures-stateless/' rel='bookmark' title='A quand de vraies architectures Stateless?'>A quand de vraies architectures Stateless?</a></li>
<li><a href='http://blog.octo.com/architectures-web/' rel='bookmark' title='Architectures Web : 3 questions à Jean-François Caenen'>Architectures Web : 3 questions à Jean-François Caenen</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/bigdata-la-fin-des-architectrures-basees-sur-les-processus-metiers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Vers des API haut niveau pour Java et NoSQL avec Spring Data</title>
		<link>http://blog.octo.com/vers-des-api-haut-niveau-pour-java-et-nosql-avec-spring-data/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=vers-des-api-haut-niveau-pour-java-et-nosql-avec-spring-data</link>
		<comments>http://blog.octo.com/vers-des-api-haut-niveau-pour-java-et-nosql-avec-spring-data/#comments</comments>
		<pubDate>Sun, 01 May 2011 14:47:03 +0000</pubDate>
		<dc:creator>Michel Domenjoud</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=21389</guid>
		<description><![CDATA[A l&#8217;heure où les nouvelles technologies de stockage de données regroupées sous les termes NoSQL et Distributed Data Grid deviennent populaires, il est intéressant de suivre l&#8217;évolution de cet écosystème et notamment des librairies d&#8217;intégration avec ces outils. Des librairies apportant un certain niveau d&#8217;abstraction émergent, avec l&#8217;espoir de voir apparaître des solutions de haut niveau [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/data-grid-or-nosql-same-same-but-different-2/' rel='bookmark' title='Data Grid or nosql? same, same but different…'>Data Grid or nosql? same, same but different…</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/soiree-spring-au-paris-jug/' rel='bookmark' title='Soirée Spring au Paris JUG'>Soirée Spring au Paris JUG</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fvers-des-api-haut-niveau-pour-java-et-nosql-avec-spring-data%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Vers%20des%20API%20haut%20niveau%20pour%20Java%20et%20NoSQL%20avec%20Spring%20Data%22%20%7D);"></div>
<p>A l&#8217;heure où les nouvelles technologies de stockage de données regroupées sous les termes <strong>NoSQL </strong>et<strong> Distributed Data Grid</strong> deviennent populaires, il est intéressant de suivre l&#8217;évolution de cet écosystème et notamment des librairies d&#8217;intégration avec ces outils.<br />
Des librairies apportant un certain niveau d&#8217;abstraction émergent, avec l&#8217;espoir de voir apparaître des solutions de haut niveau comparables aux ORM que nous utilisons pour les bases relationnelles. Nous allons nous intéresser aujourd&#8217;hui au projet <strong>Spring Data</strong>, qui propose une certaine unification pour les accès aux bases de données dites NoSQL.<span id="more-21389"></span></p>
<h1>Spring Data</h1>
<p><a href="http://www.springsource.org/spring-data">Spring Data</a> est un projet en développement et lancé en 2010, visant à simplifier l&#8217;utilisation des bases NoSQL, des frameworks <a href="http://fr.wikipedia.org/wiki/MapReduce">Map-Reduce</a>, ou d&#8217;apporter des extensions pour le support des bases relationnelles. Le projet intègre aussi progressivement le framework <a href="http://redmine.synyx.org/projects/show/hades" target="_blank">Hades</a> qui <a href="http://www.infoq.com/articles/hades_jpa_repositories_done_right">apporte la notion de <em>repository</em> pour une approche Domain Driven Developpment</a>.</p>
<p>Spring Data regroupe déjà plusieurs sous-projets dédiés à des implémentations particulières :</p>
<ul>
<li>JPA, qui apporte de nouvelles fonctionnalités pour une approche DDD avec des bases relationnelles,</li>
<li>Graph, avec une implémentation pour Neo4j,</li>
<li>Document, avec une implémentation pour MongoDB,</li>
<li>Key &#8211; Value, des implémentations pour Redis et Riak,</li>
<li>Extensions JDBC.</li>
</ul>
<p>Dans l&#8217;ensemble, les projets existants consistent à apporter une couche d&#8217;abstraction facilitant la manipulation de données avec les différents systèmes de stockage. L&#8217;apport principal de ce projet est bien sûr de faciliter l&#8217;intégration de ces technologies à un applicatif Spring, et de profiter des facilités de configuration du framework : injection de beans, configuration xml et programmation orientée aspect.</p>
<p>Nous allons voir ce que peuvent apporter ces librairies par rapport à une utilisation directe des connecteurs existants. L&#8217;équipe prévoit également le support d&#8217;autres produits tels qu&#8217;Amazon S3, Cassandra ou Hadoop.</p>
<p>En parallèle, le projet <strong>Spring Data Mapping</strong>, actuellement hébergé côté Groovy, aurait pour objectif d&#8217;apporter une solution générique de mapping Objet-Base pour plusieurs bases NoSQL.</p>
<h2>Spring Data JPA et Domain-Driven-Developpment</h2>
<p>Une des vocations du projet Spring Data est d&#8217;apporter le support pour une approche <strong>Domain Driven Developpment (<em>DDD</em>)</strong> et l&#8217;utilisation du pattern <strong><a href="http://www.codeinsanity.com/2008/08/repository-pattern.html" target="_blank" class="broken_link">Repository</a></strong>. Spring Data JPA en est la première implémentation, dédiée aux bases relationnelles. Le projet est <a href="http://redmine.synyx.org/news/27">directement repris depuis le framework Hades</a>, dont les fonctionnalités sont progressivement intégrées au socle commun de Spring Data, et doit permettre à terme une approche DDD pour les différents types de stockage supportés.</p>
<h3>Génération de Repository</h3>
<p>Le développement d&#8217;un Repository est facilité en générant automatiquement les fonctions de CRUD les plus communes d&#8217;un service d&#8217;accès aux données :</p>
<ul>
<li>save</li>
<li>findById</li>
<li>findAll (avec gestion de résultats paginés)</li>
<li>count</li>
<li>delete</li>
<li>exists</li>
</ul>
<p>L&#8217;utilisation de l&#8217;API est plutôt simple, il suffit de définir son repository via une interface étendant l&#8217;interface JpaRepository de base, et le framework se chargera du reste.</p>
<pre class="brush:java">public interface PersonRepository extends JpaRepository&lt;Person, Long&gt; { … }</pre>
<p>De plus, l&#8217;API permet, comme cela se fait en Groovy et Rails, de générer les méthodes de requêtes à partir du nom de la méthode ou en utilisant une requête nommée (@NamedQuery). Par exemple, si on souhaite ajouter une méthode de recherche par nom à notre PersonRepository :</p>
<pre class="brush:java">public interface PersonRepository extends JpaRepository&lt;Person, Long&gt; {
 List&lt;Person&gt; findByLastname(String lastname);
}</pre>
<p>Le bean injecté par Spring comportera alors une méthode générée avec l&#8217;exécution de la requête correspondante : <em>&laquo;&nbsp;SELECT * FROM User WHERE lastname = ?&nbsp;&raquo;</em>.</p>
<p>La librairie permet principalement de réduire le volume de code à écrire lorsque l&#8217;on code un Repository, mais Spring Data JPA apporte d&#8217;autres fonctionnalités intéressantes:</p>
<ul>
<li>L&#8217;approche DDD est facilitée grâce aux supports des <strong>Specifications</strong>, qui utilisent des <em><a href="http://en.wikipedia.org/wiki/Closure_(computer_science)" target="_blank">closures</a> </em>pour définir des prédicats, tout en utilisant l&#8217;API Criteria de JPA2.</li>
</ul>
<pre class="brush:java">public static Specification isPersonMinor() {
	return new Specification() {
		Predicate toPredicate(Root root, CriteriaQuery<!--?--> query,
			CriteriaBuilder builder) {
			LocalDate date = new LocalDate().minusYears(18);
			return builder.lessThan(root.get(Person_.birthDate), date);
		}
	};
}</pre>
<ul>
<li>Ajout de fonctions pour la gestion des transactions au niveau <em>Repository</em></li>
<li>Entités auditables (suivi des dates et utilisateurs de création et modification). Il s&#8217;agit d&#8217;un sujet classique en entreprise lorsque le suivi des modifications de données est stratégique. Il sera intéressant de comparer cette fonctionnalité à son équivalent <a href="http://docs.jboss.org/envers/docs/index.html" target="_blank">Hibernate Envers</a>.</li>
<li>Support de la librairie <a href="http://www.querydsl.com/" target="_blank">Querydsl</a>.</li>
</ul>
<h2>Spring Data Graph</h2>
<p>Ce projet est dédié aux bases proposant une implémentation de type graphe et fournit une implémentation pour <a href="http://neo4j.org/">Neo4j</a>.<br />
Neo4j est une base de données graphe, qui répond également aux enjeux traditionnels d&#8217;une base de données (ACIDité des transactions, gestion des accès concurrents,rollback de transaction, haute disponibilité). Pour avoir un rapide tour d&#8217;horizon de ce qu&#8217;apporte une base de données graphe et plus particulièrement Neo4j, voir <a href="http://blog.xebia.fr/2010/05/03/nosql-europe-bases-de-donnees-graphe-et-neo4j/">ici</a>.</p>
<p>Spring Data Graph propose une véritable couche d&#8217;abstraction permettant un mapping entre un modèle objet utilisé dans l&#8217;application Java et les entités stockées physiquement dans la base graphe. Spring Data Graph définit donc les notions suivantes pour la modélisation au niveau des objets (les exemples proviennent de la <a href="http://static.springsource.org/spring-data/data-graph/docs/current/reference/html/" target="_blank">documentation officielle</a>, qui propose par ailleurs un exemple complet d&#8217;une application web utilisant les différents composants de Spring) :</p>
<ul>
<li>Annotations pour définir noeuds (@NodeEntity) et relations (@RelationshipEntity)</li>
<li>Gestion des index (@Indexed)</li>
</ul>
<pre class="brush:java">@NodeEntity
class Movie {
 @Indexed
 int id;

 String title;
 int year;    

 @RelatedTo(elementClass = Actor.class, type = "ACTS_IN", direction = Direction.INCOMING)
 Set&lt;Actor&gt; cast;

 @RelatedToVia(elementClass = Role.class, type = "ACTS_IN", direction = Direction.INCOMING)
 Iterable&lt;Role&gt; roles;
}

@NodeEntity
class Actor {    

 @Indexed
 int id;
 String name;

 @RelatedTo(elementClass = Movie.class, type = "ACTS_IN")
 Set&lt;Movie&gt; cast; 

 public Role playedIn(Movie movie, String roleName) {
 Role role = relateTo(movie, Role.class, "ACTS_IN");
 role.setRole(roleName);       
 return role;
 }
}

@RelationshipEntity
class Role {
 @EndNode
 Movie movie;

 @StartNode
 Actor actor;

 String role;
}</pre>
<ul>
<li>Utilisation du pattern Repository, avec des implémentations pour gérer des opérations de CRUD, index et recherches<em></em>; ainsi que les algorithmes de parcours de graphes.</li>
</ul>
<pre class="brush:java">GraphRepository&lt;Person&gt; graphRepository = graphRepositoryFactory.createGraphRepository(Person.class);</pre>
<p>Spring Graph apporte également une couche d&#8217;abstraction sur des aspects plus techniques, entre autres:</p>
<ul>
<li>Gérer des recherches:
<ul>
<li>en utilisant des algorithmes spécifiques de parcours de graphe (Traversal)</li>
<li>en utilisant le système de recherche indexée avec un moteur d&#8217;indexation séparé (Apache Lucene est inclus par défaut).</li>
</ul>
</li>
</ul>
<p>Pour cela, il suffit d&#8217;annoter le champ à indexer: @Indexed(fulltext = true, indexName = &laquo;&nbsp;search&nbsp;&raquo;), puis d&#8217;appeler la méthode findAllByQuery(indexedField, query))</p>
<ul>
<li>Gérer les transactions avec la configuration Spring standard et SpringTransactionManager</li>
<li>Gestion de la persistance des entités avec la méthode persist()</li>
<li>Validation de beans (JSR 303) via les annotations de définition de contraintes (@Min, @Max, @Size, @Email, &#8230;)</li>
</ul>
<h3>Définition d&#8217;entités <em>cross-store</em></h3>
<p>Un autre aspect très intéressant dans cette API est le <strong>support multi-base</strong> en définissant des <strong>entités partielles</strong>, qui permet d&#8217;utiliser plusieurs systèmes de stockage pour une même entité. Actuellement, il est possible de définir une entité dont une partie des champs sera géré via JPA dans une base relationnelle classique, tandis que l&#8217;autre partie est gérée dans une base de données graphe.</p>
<p>L&#8217;exemple suivant est une modélisation simpliste d&#8217;un système de vente dans lequel les articles et les ventes sont stockés dans une base relationnelle classique, hormis les liens entre les objets vendus (&laquo;&nbsp;Les acheteurs qui ont acheté ce produit ont également acheté&#8230;), ainsi que le total des ventes pour chaque article.</p>
<pre class="brush:java">@Entity
@Table(name = "product")
@NodeEntity(partial = true)
class Product {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id")
	private Long id;

	private String name;
	private String description
	private Double price;

	@GraphProperty
	Double totalSales;

	@RelatedTo(elementClass = Product.class, type = "SAME_SALE", direction = Direction.INCOMING)
	private Set&lt;Product&gt; linkedSales;

	@RelatedToVia(elementClass = SaleConnection.class, type = "SAME_SALE", direction = Direction.INCOMING)
	private Iterable&lt;SaleConnection&gt; salesConnections;

	@OneToMany
	private Set&lt;SoldItem&gt; sales;

	@Transactional
	public SaleConnection soldTogether(Product item) {
		SaleConnection connection = relateTo(item, SaleConnection.class, "SAME_SALE");
		connection.incrementLinkWidth();
		return connection;
	}
}

@RelationshipEntity
class SaleConnection {
	@EndNode
	Product item1;

	@StartNode
	Product item2;

	int linkWidth = 0;

	public void incrementLinkWidth(){
		linkWidth++;
	}
}

@Entity
@Table(name = "sales")
class SoldItem {
	@ManyToOne
	Product productReference;

	Double soldPrice;
}</pre>
<h2>Spring Data Document</h2>
<p>Ce projet est dédié aux bases proposant une implémentation de type document, et fournit pour l&#8217;instant une implémentation pour <a href="http://www.mongodb.org/">MongoDB</a>.</p>
<p>L&#8217;implémentation apporte une surcouche au client Java fourni par Mongo et en reproduit l&#8217;essentiel des fonctionnalités en s&#8217;intégrant au framework Spring, entre autres :</p>
<ul>
<li>Configuration Spring via XML ou classes @Configuration pour les instances Mongo et la gestion des replica set</li>
<li>MongoTemplate qui offre des mécanismes d&#8217;abstraction pour interagir avec MongoDB et pour gérer la persistance des objets Java avec MongoDB de manière transparente, la gestion des collections, exécuter des commandes shell internes.</li>
<li>Fonctions de recherche avec notamment :
<ul>
<li>possibilité d&#8217;utiliser des <em>Criteria</em></li>
<li>support des requêtes géographiques</li>
</ul>
<ul>
<li>gestion d&#8217;index</li>
</ul>
</li>
</ul>
<p>Par ailleurs, la librairie apporte le support du pattern Repository de manière similaire à Spring Data JPA  avec MongoRepository:</p>
<ul>
<li>Génération des fonctions de CRUD</li>
<li>Gestion de requêtes prédéfinies au format JSON, par exemple:</li>
</ul>
<pre class="brush:java">public interface PersonRepository extends MongoRepository&lt;Person, String&gt;
  @Query("{ 'firstname' : ?0 }")
  List&lt;Person&gt; findByThePersonsFirstname(String firstname);
}</pre>
<ul>
<li>Support de Querydsl</li>
</ul>
<p>Enfin, la dernière version fraichement sortie de l&#8217;API propose d&#8217;une part un système de mapping à base d&#8217;annotations, avec notamment la possibilité de gérer les collections au sein d&#8217;un document par référence ou non:</p>
<pre class="brush:java">@Document
public class Account {
  @Id
  private ObjectId id;
  private Float total;
}

@Document
public class Person {
  @Id
  private ObjectId id;
  @Indexed
  private Integer ssn;
  @DBRef
  private List&lt;Account&gt; accounts;
}</pre>
<p>D&#8217;autre part, cette dernière release apporte comme l&#8217;API Graph un support <em>cross-store persistence</em>, permettant d&#8217;utiliser conjointement plusieurs systèmes de stockage de données.</p>
<p>Cette librairie semble plutôt aboutie et vient sans doute concurrencer sérieusement les librairies existantes comme <a href="http://code.google.com/p/morphia/">Morphia</a>, qui propose également des fonctions de mapping notamment.</p>
<h2>Spring Data Key-Value</h2>
<p>Le projet Key-Value (SDKV) est dédié aux bases proposant une implémentation clé-valeurs, et fournit des implémentations pour <a href="http://redis.io/">Redis</a> et <a href="http://wiki.basho.com/">Riak</a>.</p>
<p>Il s&#8217;agit pour l&#8217;instant essentiellement d&#8217;une couche d&#8217;abstraction au dessus des librairies de bas niveau existantes, qui permet principalement de tirer avantage d&#8217;une configuration Spring. Ces deux librairies semblent encore à un niveau de  maturité assez faible et n&#8217;apportent pour l&#8217;instant pas beaucoup par rapport à une utilisation directe des connecteurs.</p>
<h3>Redis</h3>
<p>L&#8217;implémentation SDKV pour Redis est une surcouche aux connecteurs Jedis, JRedis et RJC, qui apporte notamment:</p>
<ul>
<li>Configuration simple via XML, par exemple :</li>
</ul>
<pre class="brush:xml">&lt;bean id="jedisConnectionFactory" class="org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory"&gt;
	&lt;property name="hostName" value="localhost"/&gt;
	&lt;property name="port" value="6379"/&gt;
	&lt;property name="timeout" value="5000"/&gt;
	&lt;property name="pooling" value="true"/&gt;
&lt;/bean&gt;

&lt;bean id="redisTemplate" class="org.springframework.data.keyvalue.redis.core.RedisTemplate"
	p:connection-factory-ref="jedisConnectionFactory"/&gt;</pre>
<ul>
<li>Utilisation d&#8217;objets plutôt que de dialoguer directement avec Redis grâce à la classe RedisTemplate
<ul>
<li>classes correspondant aux opérations de Redis (Value, List, Set, ZSet, Hash et Bound*)</li>
<li>fonctions de messaging (Send/Publish/Subscribe)</li>
</ul>
</li>
<li>Possibilité d&#8217;utiliser différents mécanismes de sérialisation pour stocker des objets</li>
</ul>
<p>Plusieurs articles on déjà été publiés sur le sujet:</p>
<ul>
<li><a href="http://pietrowski.info/2011/01/spring-data-redis-tutorial/">SpringData &#8211; Redis tutorial</a></li>
<li><a href="http://java.dzone.com/articles/movie-recommendation-app-using">Movie Recommendation App using Spring Data and Redis</a></li>
<li><a href="http://java.dzone.com/articles/creating-an-application-using-spring-data-with-redis-as-datastore-part-1">Creating an Application using Spring Data with Redis as Datastore &#8212; Part 1</a></li>
<li><a href="https://github.com/SpringSource/spring-data-keyvalue-examples">Exemples sur le github de SpringSource</a></li>
</ul>
<h3>Riak</h3>
<p>Là aussi, SDKV propose une surcouche au client Java développé par Basho (la société derrière Riak). Une base de données Riak est nativement accédée via une API REST/HTTP, utilisant les drivers Apache Commons.</p>
<p>La librairie apporte notamment :</p>
<ul>
<li>Configuration simple par XML, par exemple:</li>
</ul>
<pre class="brush:xml">&lt;bean id="riakTemplate"
      p:defaultUri="http://localhost:8098/riak/{bucket}/{key}"
      p:mapReduceUri="http://localhost:8098/mapred"/&gt;</pre>
<ul>
<li>Utilisation d&#8217;objets plutôt que de dialoguer directement avec Riak grâce à la classe RiakTemplate
<ul>
<li>pour les fonctions d&#8217;accès et de stockage</li>
<li>l&#8217;utilisation de l&#8217;algorithme Map/Reduce</li>
<li>les fonction de liaison entre les entrées et de parcours des listes liées</li>
</ul>
</li>
<li>Gestion asynchrone des échanges avec la base de données avec des <em>callbacks</em></li>
<li>Utilisation de services personnalisés de conversion d&#8217;objets vers Riak ou de ClassLoader depuis Riak</li>
</ul>
<h2>Spring Data JDBC Extensions</h2>
<p>Cette partie de Spring Data se situe un peu en marge du reste car il s&#8217;agit ici de fournir des extensions de configuration spécifiques à certaines implémentations de bases de données relationnelles.</p>
<p>La première version du projet comporte des extensions pour les bases de données Oracle, qui constituent un portage du code d&#8217;un module auparavant payant de Spring, le <a href="http://www.springsource.org/node/617" target="_blank">Advanced Pack for Oracle Database</a>. Cette extension doit notamment permettre un support transparent pour les applications de fonctionnalités telles que le <em>Fast Connection Failover</em> d&#8217;Oracle RAC, Advanced Queuing, et des types de données complexes (XML, STRUCT, ARRAY).</p>
<h2>Vers une abstraction de plus haut niveau?</h2>
<h3>Spring Data Mapping</h3>
<p>Ce dernier projet plutôt ambitieux vise à fournir un framework mutualisé de mapping objet pour les différents implémentations de stockage de données. C’est finalement une surcouche aux projets précédents qui cherche, j’imagine, à décorréler la modélisation du stockage physique. A l&#8217;heure actuelle, le projet est simplement mentionné dans la page du projet Spring Data, il n&#8217;y a pas de version SNAPSHOT disponible. Le projet est pour l&#8217;instant en Groovy, mais devrait être migré en Java pour s&#8217;intégrer à Spring Data.</p>
<p>D&#8217;après ce qu&#8217;on peut voir des sources existantes, il serait bien possible de définir un mapping d&#8217;objets de manière relativement  indépendante de la base de données : on trouve un projet core, et des implémentations pour de nombreuses technologies: Gemfire, Hibernate, AppEngine, Redis, Mongo, Cassandra et d&#8217;autres&#8230;</p>
<h3>Hibernate OGM</h3>
<p><a href="http://community.jboss.org/wiki/OverviewofHibernateOGM">Hibernate OGM</a> est un projet démarré en juillet 2010 et mené par <a href="http://twitter.com/emmanuelbernard" target="_blank">Emmanuel Bernard</a> chez JBoss. Le projet a été repris d&#8217;un essai d&#8217;une implémentation JPA-like pour <a href="http://www.slideshare.net/maniksurtani/infinspan-inmemory-data-grid-meets-nosql">Infinispan</a>, le moteur de grille de données open source de JBoss. A l&#8217;heure actuelle, le projet semble être à un stade plutôt expérimental et bien moins avancé que Spring Data, mais il sera intéressant de suivre son évolution et l&#8217;orientation qui sera suivie, car les deux projets seront sans doute concurrents.</p>
<p>Concrètement, Hibernate OGM souhaite utiliser Hibernate Core pour stocker des données dans une grille de données distribuée, en l&#8217;occurrence Infinispan. L&#8217;objectif est de réutiliser l&#8217;implémentation existante de JPA plutôt que de repartir de zéro, pour mapper des entités et des relations.</p>
<h1>Pour conclure</h1>
<p>Pour l&#8217;instant, en dehors de l&#8217;API Graph, Spring Data est en cours de développement et il n&#8217;est donc pas encore question d&#8217;utiliser ces librairies en production. Néanmoins, l&#8217;avancement actuel des différentes librairies laisse déjà présager de plusieurs atouts à leur utilisation :</p>
<ul>
<li><strong>intégration au framework Spring</strong> et apport de ses facilités de configuration.</li>
<li><strong>abstraction</strong> par rapport aux implémentations des différentes solutions de stockage NoSQL et <strong>apport de surcouches aux connecteurs</strong>, notamment grâce aux systèmes de mapping par <strong>annotations</strong>. Il y a encore du travail sur ce point pour offrir toutes les fonctionnalités de chaque base de données et y gagner réellement par rapport à l&#8217;utilisation d&#8217;une API de plus bas niveau.</li>
<li>développement facilité dans une <strong>approche orientée Domain-Driven-Developpment</strong>.</li>
</ul>
<p>Mais la perspective la plus intéressante est l&#8217;émergence de solutions unifiées de mapping objet/base permettant de limiter les spécificités à chaque base. Spring Data et Hibernate OGM ont un potentiel intéressant car ils ouvrent la voie vers une abstraction de plus haut niveau pour des implémentations et surtout des concepts de stockage de données très divers.</p>
<p>En s&#8217;attaquant à ces problématiques de mutualisation, ces projets attaquent la question complexe des frontières entre ces différents concepts :</p>
<ul>
<li><strong>Peut-on espérer avoir une abstraction suffisante pour passer d&#8217;une manière transparente d&#8217;une implémentation relationnelle à certains modes de stockage NoSQL?</strong></li>
</ul>
<p>Spring Data tente d&#8217;adresser ce problème avec le socle commun du framework et le projet Spring Data Mapping, de même qu&#8217;Hibernate OGM en réutilisant Hibernate Core pour Infinispan. Mais il faudra être très prudent sur ce point et ne pas tomber dans le piège de vouloir faire du relationnel classique dans une base clé-valeur ou document par exemple, en risquant de perdre les avantages de ces représentations.</p>
<ul>
<li><strong>Dans quelle mesure peut-on outiller les développements pour utiliser conjointement et de manière transparente plusieurs systèmes de représentation des données?</strong></li>
</ul>
<p>Dans ce sens, Spring Data adresse directement cette frontière, avec la notion d&#8217;entités partielles pour l&#8217;API Graph : une même application peut être amené à utiliser plusieurs techniques de stockage conjointement, et nous avons besoin d&#8217;outils pour faciliter ces développements.</p>
<p>Finalement, les deux projets étudiés ici adressent un point essentiel : le mouvement NoSQL ne propose pas simplement de nouvelles techniques de stockage, mais vise surtout à adresser les solutions adaptées à chaque problème, en arguant le fait qu&#8217;il n&#8217;existe pas de solution unique parfaite.</p>
<p>L&#8217;écosystème autour de NoSQL et du stockage distribué est bien vivant, et surtout il est bien parti pour gagner en maturité et en accessibilité pour les développements Java. On suivra donc avec attention la sortie des premières versions définitives!</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=21389" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/data-grid-or-nosql-same-same-but-different-2/' rel='bookmark' title='Data Grid or nosql? same, same but different…'>Data Grid or nosql? same, same but different…</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/soiree-spring-au-paris-jug/' rel='bookmark' title='Soirée Spring au Paris JUG'>Soirée Spring au Paris JUG</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/vers-des-api-haut-niveau-pour-java-et-nosql-avec-spring-data/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>QCon London 2011: un peu de process, beaucoup d&#8217;architecture et de la performance pour passer à l&#8217;échelle</title>
		<link>http://blog.octo.com/qcon-london-2011-un-peu-de-process-beaucoup-darchitecture-et-de-la-performance-pour-passer-a-lechelle/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=qcon-london-2011-un-peu-de-process-beaucoup-darchitecture-et-de-la-performance-pour-passer-a-lechelle</link>
		<comments>http://blog.octo.com/qcon-london-2011-un-peu-de-process-beaucoup-darchitecture-et-de-la-performance-pour-passer-a-lechelle/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 08:06:48 +0000</pubDate>
		<dc:creator>Marc Bojoly</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Data Grid]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[QCON]]></category>
		<category><![CDATA[QCon London 2011]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=20826</guid>
		<description><![CDATA[Il y a une semaine, avait lieu la 5° édition de QCon, un événement incontournable pour l&#8217;architecture de SI, pour sentir les tendances de l&#8217;industrie, pour détecter quelques nouveautés. 6 tracks parallèles, un total de 90 sessions. Impossible de participer à tout mais voici ce que nous en avons envie de retenir : Des sujets [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/trois-jours-a-qcon-london-2010-tendances-et-confirmations/' rel='bookmark' title='Trois jours à QCon London 2010 : Tendances et Confirmations'>Trois jours à QCon London 2010 : Tendances et Confirmations</a></li>
<li><a href='http://blog.octo.com/passer-du-shell-a-puppet/' rel='bookmark' title='Passer du shell à Puppet'>Passer du shell à Puppet</a></li>
<li><a href='http://blog.octo.com/coffre-fort-archivage-electronique-beaucoup-de-similarites-et-une-difference-structurelle/' rel='bookmark' title='Coffre fort &amp; archivage électronique : beaucoup de similarités et une différence structurelle'>Coffre fort &#038; archivage électronique : beaucoup de similarités et une différence structurelle</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fqcon-london-2011-un-peu-de-process-beaucoup-darchitecture-et-de-la-performance-pour-passer-a-lechelle%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22QCon%20London%202011%3A%20un%20peu%20de%20process%2C%20beaucoup%20d%27architecture%20et%20de%20la%20performance%20pour%20passer%20%C3%A0%20l%27%C3%A9chelle%22%20%7D);"></div>
<p>Il y a une semaine, avait lieu la 5° édition de QCon, un événement incontournable pour l&#8217;architecture de SI, pour sentir les tendances de l&#8217;industrie, pour détecter quelques nouveautés. 6 tracks parallèles, un total de 90 sessions. Impossible de participer à tout mais voici ce que nous en avons envie de retenir :<br />
<span id="more-20826"></span></p>
<h1>Des sujets d’actualité&#8230;voire innovants</h1>
<h2>Agile, c’est maintenant au tour de l’entreprise</h2>
<p>Cela passe par <strong>l’organisation des équipes </strong>et <a href="http://qconlondon.com/dl/qcon-london-2011/slides/CraigLarman_ScalingLeanAgileLargeMultisiteOrOffshoreDelivery.pdf">la keynote d&#8217;ouverture par Craig Larman</a> nous le rappelle. Cela confirme également la tendance du marché vers ces pratiques de développement logiciel ou produit (puisque C. Larman a notamment parlé de retours d’expérience chez Xerox)  : il ne s&#8217;agit plus de convaincre que c’est une manière efficace de “faire du logiciel” mais de voir comment améliorer ces processus et passer à l&#8217;échelle. Alors<strong> “Features teams are better than component team” </strong>Craig Larman dans le texte et il s’agit de privilégier un découpage du produit en domaine qui ont chacun leur organisation scrum, leur PO, leur équipe pluridisciplinaire. <strong>En somme une organisation vue du client et pas vue de l’architecture (Loi de Conway)</strong>. Dès lors, il est néanmoins important de <strong>formaliser des “Communities of Practices”</strong> : des rencontres d’experts (donc des personnes qui partagent des sujets et des problématiques communs) cross-team et finalement transverses à l’organisation, des lieux et temps de rencontre formalisés pour échanger, partager, progresser, cultiver le sentiment d’appartenance (vous n’avez qu’à regarder toutes les rencontres/échanges que mettent en place les plus grands cuisiniers français&#8230;). Enfin, il faut rappeler que le sprint règle et rythme la vie du produit, pas de l’équipe et on tentera de colocaliser les équipes par domaine.</p>
<p><strong>Cela passe également par l’organisation au sein de l’équipe</strong>. <a href="http://qconlondon.com/dl/qcon-london-2011/slides/RoyOsherove_TeamLeadershipInTheAgeOfAgile.pdf">Roy Osherove l’a vécu</a> et l’affirme &laquo;&nbsp;Most team leaders use the wrong kind of leadership for the current team stage”. Il définit ainsi différents niveaux de maturité d’une équipe et rappelle que trop souvent est faite l’hypothèse qu’une équipe agile est auto-organisée et doit seulement être coachée alors que souvent, il s’agit de faire grandir son équipe et adapter son management au niveau de progression de l’équipe.</p>
<p><img class="alignright size-full wp-image-21043" title="ScreenShot085" src="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot085.png" alt="" width="391" height="269" /></p>
<p><strong>Cela passera également par la “prod” et c’est dans cette mouvance que s’inscrit le mouvement devops</strong>. On notera l’agréable <a href="http://qconlondon.com/dl/qcon-london-2011/slides/JezHumble_RemediationPatternsHowToAchieveLowRiskReleases.pdf">session de Jez Humble</a> qui prolonge des choses que nous avions évoqué lors d’<a href="http://www.universite-du-si.com/fr/conferences/4-usi-2009/sessions/797-quelques-idees-issues-des-grands-du-web-pour-remettre-en-cause-vos-reflexes-d-architectes">USI 2009</a>. Il y a un enjeu fort à fiabiliser les mises en production et les “remediation patterns” y participent (Cf. plus bas). <em>A noter que Jez Humble sera présent (ainsi que John Allspaw) à <a href="http://www.universite-du-si.com/fr/conferences/8-paris-usi-2011/sessions/967-le-deploiement-en-continu">USI 2011</a></em></p>
<p>Pour aller plus loin, <a href="http://qconlondon.com/dl/qcon-london-2011/slides/ChrisRead_and_DanNorth_AgileOperationsOptimisingTheBusinessOneShellScriptAtATime.pdf">Dan North et Chrid Read (DRW Trading)</a> étaient là pour nous parler de “Agile Operations”, issue de la culture devops (rapprochement entre les pratiques/outils des études et production) et de “Lean Operations” (dirigé par la <a href="http://blog.octo.com/tag/theorie-des-contraintes/">théorie des contraintes</a> dont l’auteur principal est <a href="http://www.universite-du-si.com/fr/conferences/3/sessions/903">Eliyahu M. Goldratt</a>) avec pour objectif de réduire les gaspillages. Trois exemples concrets : <strong>superviser en une ligne de shell</strong> avec ping et mailx (ça rappelle le <a href="http://teddziuba.com/2010/10/taco-bell-programming.html">Taco Bell Programming</a>), <strong>automatiser la configuration système</strong> à l&#8217;aide de Puppet/Chef pour éviter les process complexes et interminables entre la commande et la livraison d&#8217;environnements configurées ou encore <strong>améliorer la stabilité du système par du test-driven infrastructure</strong> (ex: pre-commit hook SVN pour valider la conf réseau avant même de commiter, utiliser <a href="http://linux.softpedia.com/get/System/Networking/sentinel-10480.shtml">sentinel</a> pour tester en continu l&#8217;état du réseau, etc.).</p>
<h2>Distributed Data Storage &amp; nosql : un sujet d’actualité dans les industries de la Finance et du Web.</h2>
<p><strong>Distributed Data Grid et solutions NoSQL ont suivi des chemins différents mais adressent des sujets similaires. D’un côté, on est passé par la mémoire (shared memory), de l’autre par la parallélisation (shared nothing)</strong>. D’un côté, le besoin d’optimiser la latence (une obsession dans le domaine financier), de l’autre, le besoin d’absorber des débits de requêtes de plus en plus importants, <a href="http://www.allthingsdistributed.com/2010/11/cluster_gpu_instances_amazon_ec2.html">Latence vs. débit</a>. Quoiqu’il en soit, <strong>tout cela semble converger</strong>, à simplifier le contrat &amp; ACID, <strong>à sortir de la contrainte du schéma</strong> (imposée par le RDBMS) &#8211; car un système de stockage doit être capable de gérer plusieurs versions de données - <strong>tout cela cherche à sortir de la contrainte du disque</strong> &#8211; car les accès mémoire sont 100x plus rapides que les accès disques &#8211; c’est d’autant plus vrai que l’infrastructure a évolué depuis les RDBMS avec un offre de RAM de plusieurs Go. Cela n’est pas sans rappeler ces deux papiers de 2008; (1) OLTP Through the Looking Glass, and <a href="http://portal.acm.org/citation.cfm?doid=1376616.1376713">What We Found There</a> et (2) <a href="http://cs-www.cs.yale.edu/homes/dna/papers/vldb07hstore.pdf">The End of an Architectural Era</a>.</p>
<p>Alors certes, les <strong>Distributed Data Grid ont trouvé leur place dans le monde de la banque et NoSQL dans le monde du web</strong>. NetFlix nous a raconté sa stratégie et sa <a href="http://qconlondon.com/dl/qcon-london-2011/slides/SiddharthAnand_NoSQLNetflix.pdf">mise en oeuvre de migration vers AWS</a> plutôt que de recontruire un nouveau Data Center. <strong>Les difficultés qu’ils ont rencontrés avec SimpleDB semblent corroborer ce qui est écrit dans ce <a href="http://www.cidrdb.org/cidr2011/Papers/CIDR11_Paper15.pdf">papier</a></strong>. Bref, ce n’était pas de la publicité pour SimpleDB; bien au contraire et, à tort ou à raison, cela semble justifier leur choix de migrer vers Cassandra (et d’inverstir dans des nouveaux développements notamment au niveau des stratégies de réplication). <strong>Facebook nous a fait une présentation des travaux qu’ils réalisaient avec <a href="http://qconlondon.com/dl/qcon-london-2011/slides/KannanMuthukkaruppan_HBaseFacebook.pdf">HBase</a></strong>. <strong>The Guardian, célèbre journal anglais, a <a href="http://qconlondon.com/dl/qcon-london-2011/slides/MatthewWall_WhyIChoseMongoDBForGuardianCoUk.pdf">mis en oeuvre MongoDB</a></strong>.</p>
<p>Des acteurs qui s’accordent sur le fait qu’il y a des manques tout de même : des APIs clientes encore trop simplistes (pas de timeout&#8230;), des limitations autour de l’upgrade du cluster sans interruption de services&#8230;.<br />
<strong>Reste que d’autres comme <a href="http://qconlondon.com/dl/qcon-london-2011/slides/NickKallen_DataArchitectureAtTwitterScale.pdf">Twitter restent sur MySQL</a> et semblent satisfaits</strong> . Nick Kallen démontre comment Twitter réalise le stockage des tweets, l’affichage de la timeline et la gestion du graph social dans MySQL (avec notamment l’utilisation de <a href="https://github.com/twitter/flockdb">FlockDB</a> ou <a href="https://github.com/twitter/gizzard">Gizzard</a>) en fonction des contraintes de performance. Pour info, on y retrouve quelques ordres de grandeurs qui permettent de positionner les contraintes auxquelles est soumise l’architecture : à titre d’exemple, 1100 tweets sont écrits par seconde. En revanche, la timeline sert 2,1millions de lectures par seconde (la timeline est pré-calculée et stockée dans memcached), et le graphe social doit gérer 20k modification / sec.</p>
<p>A noter que ce domaine est encore en pleine évolution. La preuve avec cette initiative intéressante de <a href="http://www.benstopford.com/">Ben Stopord</a> <strong>qui part du constat que certaines données doivent être partitionnées et d’autres répliquées; et c’est évident, <a href="http://qconlondon.com/dl/qcon-london-2011/slides/BenStopford_GoingBeyondTheDataGridCoherenceNormalisationJoinsAndLinearScalability.pdf">cela dépend des cas d’usage</a></strong>. Jusque là, “rien de génial” mais l’innovation dans ODC c’est que ce choix réplication vs. partitionnement, bien que définit par configuration en fonction de l’utilisation qui est faite de la donnée (type de requête&#8230;), n’impacte que le stockage de la donnée et absolument pas la modélisation qui peut rester relationnelle&#8230; Ainsi ODC, basée sur Cohérence,  permet par configuration d’assurer ces deux modes de fonctionnement et du même coup de gérer des jointures, des indexations&#8230;</p>
<p>En somme, un domaine d’innovation si on le compare à celui des RDBMS mais qui trouve sa place, son terrain de jeu.<br />
<a href="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot086.png"><img class="aligncenter size-full wp-image-21049" title="ScreenShot086" src="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot086.png" alt="" width="454" height="289" /></a></p>
<h2>Big Memory : Azul, Terracotta&#8230;la limite de la JVM à 3 ou 4Go n’est plus acceptable</h2>
<p><strong>Une tendance intéressante qui part du constat que les évolutions d’infrastructure nous amènent à des serveurs pouvant proposer sans problème 50 Go de RAM voir plus. Or nos JVMs (enfin les Garbage Collector) ont bien du mal à dépasser les 3 ou 4 Go</strong> ce qui conduit inexorablement à une multitude de process en parallèle&#8230; avec ce que cela peut impliquer en terme de supervision.<br />
<strong>Azul propose sa JVM Zing qui inclue un GC sans pause</strong>. Il n&#8217;y a donc plus à avoir peur des minutes où le GC tournerait pour faire le ménage dand la heap d&#8217;une JVM de 100GB. La seule (grosse) limite actuelle de cette JVM est qu&#8217;il faut un noyau Linux patché ou exécuter son application dans une VM (au sens OS, pas une JVM). Dans ce dernier cas, la JVM est remplacée par une JVM proxy qui renvoie tout vers la JVM Zing présente dans une autre VM (Zing Virtual Appliance) avec un noyau patché.<br />
<strong><a href="http://qconlondon.com/dl/qcon-london-2011/slides/KunalBhasin_ABitOfAlgebraMassiveAmountsOfInMemoryKeyValueStorageInMemorySearchJavaNoSQLKiller.pdf">Terracotta </a> propose des extensions à Ehcache; Big Memory, qui vise à contourner la JVM et à utiliser directement la RAM</strong> disponible pour stocker de l’information. BigMemory doit bien entendu être couplé à Terracotta Server qui va ainsi rajouter la couche “scalabilité” et persistence.</p>
<h2>Les langages fonctionnels et plus particulièrement la programmation orientée acteur continuent leur &laquo;&nbsp;bonhomme de chemin&nbsp;&raquo;&#8230;</h2>
<p><strong>A commencer par Erlang; un langage fonctionnel pensé pour construire des applications concurrentes, distribuées et résilientes</strong>. Pour cela, il permet la création de processus légers (appelés acteurs) en taille mémoire nécessaire, en temps de création mais aussi en temps d&#8217;ordonnancement. Il est ainsi facilement envisageable d&#8217;avoir une application avec plusieurs centaines de millier de ces processus. Ces processus sont gérés (créés et schedulés) directement par la VM Erlang évitant ainsi les allers-retours entre le noyau de l&#8217;OS et l&#8217;espace utilisateur. <strong>La philosophie de la programmation par acteurs est &laquo;&nbsp;share nothing&nbsp;&raquo;, contrairement à la programmation par threads</strong>. Chaque acteur communique alors avec les autres en envoyant des messages asynchrones et traite les messages reçus les uns à la suite des autres. Ces acteurs travaillent donc tous en parallèle sur plusieurs coeurs d&#8217;un même CPU et sur plusieurs CPU distribuées sur plusieurs machines. <strong>Enfin et concernant la résilience</strong>, en cas de “crash” d’un des processus, <strong>les processus préalablement liés sont notifiés</strong> et prennent la décision adéquate. Ainsi<strong> des patterns tel que &laquo;&nbsp;Supervisor &amp; Worker&nbsp;&raquo;</strong> permettent de configurer une stratégie de redémarrage des workers (combien de redémarrage successif du même worker avant d&#8217;abandonner, relancer seulement le worker qui a planté ou l&#8217;ensemble des workers supervisés, …). <strong>En plus de cela, un certain nombre d&#8217;autres mécanismes tel que le déploiement à chaud</strong> d&#8217;une nouvelle version d&#8217;une application, l&#8217;activation de cette nouvelle version, le rollback à une version précédente, …  <strong>apportent aux applications développées <a href="http://qconlondon.com/london-2011/file?path=/qcon-london-2011/slides/SteveVinoski_LetItCrashExceptWhenYouShouldnt.pdf">en Erlang une disponibilité maximale</a></strong>.</p>
<p><strong>Ce type de programmation n’est pas sans inspirer le développement de nouveaux produits  basés sur l’asynchonisme et des approches orientées évènements</strong> (type <a href="http://www.eecs.harvard.edu/~mdw/papers/seda-sosp01.pdf">SEDA</a>). Ces approches &#8211; à la <a href="http://qconlondon.com/dl/qcon-london-2011/slides/StefanTilkov_NodeJsAsynchronousIOForFunAndProfit.pdf">Node.js</a> , ou encore <a href="http://www.tornadoweb.org/">Tornado</a> visent à dépasser le “<a href="http://www.kegel.com/c10k.html">C10k Problem</a>” en découplant requête et réponse (qui sera traité dans une callback) et ainsi assurer une meilleure concurrence.</p>
<p><a href="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot087.png"><img class="alignleft size-full wp-image-21052" title="ScreenShot087" src="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot087.png" alt="" width="507" height="306" /></a></p>
<p><strong>L&#8217;objectif de ces outils est ainsi de pouvoir supporter un très grand nombre de connexions simultanées</strong> (grand nombre de requêtes à la seconde ou grand nombre de connexions longues (ex: long polling, websocket, …)) et chacun y va de sa solution :</p>
<ul>
<li><strong>Node.js propose des API IO asynchrones</strong>. En effet Node.js n&#8217;exécute le code que sur un seul thread qui traite toutes les requêtes en parallèle et switch de requête dès qu&#8217;il exécute un appel IO via une API asynchrone. Ainsi le traitement du résultat de cet appel sera traité dans un handler. Cette approche est dite event-driven programming</li>
<li><strong>Erlang et Haskell </strong>(qui utilisent aussi des green-threads légers en mémoire, cpu et context switching) <strong>présentent un <a href="http://qconlondon.com/london-2011/file?path=/qcon-london-2011/slides/GregoryCollins_HighPerformanceWebApplicationsInHaskell.pdf">modèle hybride</a> complètement transparent pour le code</strong>. Le code est écrit avec des API IO synchrones (plus simple) mais la VM utilise quand cela est possible des appels IO asynchrones (<code>epoll()</code> par exemple) ou utilise le threading classique niveau OS lorsqu&#8217;un appel bloquant est obligatoire (accès fichier par exemple).  A noter l’initiative de Basho, éditeur de Riak, qui a développé <a href="http://qconlondon.com/dl/qcon-london-2011/slides/JustinSheehy_WebmachineAPracticalExecutableModelOfHTTP.pdf">Web Machine</a> ; un <a href="http://webmachine.basho.com/diagram.html">condensé d’HTTP</a>.</li>
</ul>
<p><strong>Au delà de la performance, un des challenge de ce type d’outil</strong> (contrairement à la programmation orientée acteur où le mindset, le paradigme est différent) <strong>concerne le développement</strong> : comment offrir des APIs qui fonctionnent en asynchrone même si le comportement est synchrone et qui n’impactent pas le code, sa lisibilité? quid de l’outillage, du debug etc&#8230;</p>
<h2>La résilience  qui, avec l’efficience des systèmes est certainement un des prochains challenges (enfin&#8230;)</h2>
<p><strong>A</strong><strong>lors la résilience a été  au niveau langage avec des plateformes type Erlang qui ont fait leur preuve</strong>. La plateforme OTP (Open Telecom Platform) d&#8217;Erlang permet de construire une hierarchie de supervision de sous-systèmes à base d&#8217;acteurs (en s&#8217;appuyant sur le pattern &laquo;&nbsp;Supervisor &amp; worker&nbsp;&raquo; précédemment décrit) capable de supporter le crash d&#8217;un sous-système et de se réamorcer. Ce guide présente plus en détail comment <a href="http://www.erlang.org/doc/design_principles/users_guide.html">Erlang gère la résilience</a>.</p>
<p><strong>Au niveau des tests où l’on se rend compte que les tests de résilience arrivent très tôt dans le processus de développement</strong>, avant même les tests de performance qui nécessitent la mise en place d’infrastructure représentative (voire de réaliser des “parallel runs”)</p>
<p><strong>Mais également au niveau delivery et déploiement</strong> avec Jez Humble : les <a href="http://qconlondon.com/dl/qcon-london-2011/slides/JezHumble_RemediationPatternsHowToAchieveLowRiskReleases.pdf">“remediation patterns”</a>. On y trouve des patterns comme :</p>
<ul>
<li><strong>“feature toggle”</strong> qui vise à décorréler le déploiement du code du déploiement d’une fonctionnalité,</li>
<li>le <strong>“Canary Releasing”</strong> qui vise à déployer une partie de la population sur la nouvelle  version de l’application (une solution pour l’A/B testing, les tests de performance&#8230;); avec un sujet sur la base de données qui peut être adressé soit en reconciliant les deux bases, soit en stockant des évènements (cf. Event Sourcing) et en rejouant les évènements, soit en assurant la compatibilité ascendante du schéma (certainement la meilleure solution mais celle qui demande le plus de discipline, car le plus important sera de nettoyer le schéma à terme). <a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.de/de/de/research/pubs/archive/36500.pdf" class="broken_link">Ce papier de Google</a> traite malheureusement pas assez en détail de ces sujets.</li>
<li> ou encore l’<strong>incremental delivery</strong></li>
</ul>
<h1>Des domaines qui continuent de s’améliorer (et où l’on considère bien souvent que plus rien ne se passe)</h1>
<h2>La qualité logicielle et la réarchitecturation des systèmes</h2>
<p>Rien de nouveau mais ça va mieux en le disant :</p>
<blockquote><p>“All architecture is design but not all design is architecture. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.”<br />
Grady Booch</p></blockquote>
<p><strong>Concernant la qualité logicielle, un des sujets est certes de choisir les indicateurs mais surtout de choisir la <a href="http://qconlondon.com/dl/qcon-london-2011/slides/ErikD%25C3%25B6rnenburg_SoftwareQualityYouKnowItWhenYouSeeIt.pdf">représentation de ces derniers </a></strong>(et quelques part choisir les façons de communiquer qui seront les plus adaptées). Cela n’est pas sans rappeler le mouvement <a href="http://www.legrandbi.com/2011/02/beautiful-visualization/">Data Visualization</a> si cher à notre Joseph national (spécial dédicace :o) ).  On utilisera alors à façon treemap facilitant la visualisation de la taille du code, la complexité cyclomatique ou encore des ratios nombre de LOC sur nombre de LOC de tests. A noter qu’il est possible de représenter le code sous forme de ville en 3D avec <a href="http://www.inf.usi.ch/phd/wettel/codecity.html">CodeCity</a>.</p>
<h2>Les plateformes telles que Java &amp; .Net continuent de s’améliorer</h2>
<p><strong>Alors il y a du classique </strong>avec <a href="http://qconlondon.com/dl/qcon-london-2011/slides/JuergenHoeller_Spring31AndBeyondThemesAndTrends.pdf">Spring 3.1, Servlet 3.1</a> ou encore <a href="http://qconlondon.com/london-2011/file?path=/qcon-london-2011/slides/JeanBaptisteEvain_AdvancedReflection.pdf">Mono Cecil</a>; une librairie .Net Open Source cross-platform (de .NET à WindowsPhone 7) permettant d’étendre les fonctionnalités de réflexion classiques de la plateforme .NET (par exemple sur les champs masqués derrière une propriété), mais également de manipulation de bytecode. Cela permet de coder simplement des fonctionnalités de type AOP par exemple.</p>
<p><strong>Et du moins classique&#8230; </strong>Java est adopté dans des environnements sensibles à la performance comme la finance.<br />
<strong><a href="http://qconlondon.com/dl/qcon-london-2011/slides/RichardTibbetts_ComplexEventProcessingDSLForHighFrequencyTrading.pdf">StreamBase, un CEP haute fréquence implémenté en Java</a></strong> avec , il faut bien l’avouer, quelques optimisations ou spécificités, notamment sur la gestion du garbage collection ou la génération du bytecode avec Janino (un compilateur à la volée et en mémoire)&#8230;. <strong><a href="http://www.linkedin.com/pub/cameron-purdy/0/10/23a">Cameron Purdy</a>, ancien CEO de Tangosol et vice président de Oracle Fusion Middleware a également confirmé cette tendance en présentant plusieurs axes de travail (la sortie de ces travaux n’étant même pas encore confirmée) permettant à Java d&#8217;être plus performant (notamment sur la latence, cruciale dans le domaine financier)</strong>. En bref, pour le moment de la pure R&amp;D, qui sortirait peut-être dans une version 9 de Java, avec notamment</p>
<ul>
<li><strong>une API pour du bus de message basse latence</strong> directement sur RDP/Infiniband ou TCP/IP, JMS étant “trop lourd” dans ce cas. Java chercherai donc à jouer sur le même terrain que <a href="http://www.zeromq.org/">ØMQ</a>.</li>
<li><strong>un accès direct et distant à la RAM <a href="http://en.wikipedia.org/wiki/Remote_direct_memory_access">RDMA</a> sans passer par le noyau (oui, oui vous avez bien compris)</strong><strong>,  pour là encore gagner en latence</strong>. Le prix à payer est que ces innovations utilisent très fortement les optimisations (et donc les particularités) de l’OS et du matériel&#8230; Les premières implémentations de ces API sont visiblement prévues sur les <a href="http://www.oracle.com/us/products/middleware/exalogic/index.html">appliances Exalogic</a>. Issues de la synergie que lui offre désormais un fondeur pour des puces dédiées (Sun), un OS et un hyperviseur maison (Oracle Unbreakable Linux) et une JVM, ces appliances sont les Rolls-Royce d&#8217;Oracle sur lesquelles l&#8217;éditeur mise beaucoup dans le monde de la finance. <strong>Et pour être franc, tout cela sent le “Java propriétaire”&#8230;</strong></li>
</ul>
<h2>HTML5 comme plateforme</h2>
<p>Mark S. Miller de Google a ainsi présenté les concepts qui sous-tendent la <a href="http://qconlondon.com/london-2011/file?path=/qcon-london-2011/slides/MarkS.Miller_SecureDistributedProgrammingOnEcmaScript5HTML5Platforms.pdf">sécurité pour le cross-scripting de ECMAScript (JavaScript) 5</a>. <strong>L&#8217;objectif est clairement de sortir d&#8217;une logique page web et de construire des objets JavaScript qui interagissent entre eux à travers Internet</strong>&#8230; Un objectif qui n’est pas sans rappeler la notion de “mashup” mais qui surtout nécessitent de repenser la Same Origin Policy.<br />
<a href="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot088.png"><img class="aligncenter size-full wp-image-21059" title="ScreenShot088" src="http://blog.octo.com/wp-content/uploads/2011/03/ScreenShot088.png" alt="" width="524" height="307" /></a></p>
<p><strong>Même Adobe se positionne sur HTML5 voyant là un standard permettant de cibler le plus grand nombre de plateformes</strong>. Cela commence par l’enrichissement de sa gamme de produit; DreamWeaver avec entre autre les nouvelles balises de <a href="http://www.w3.org/TR/html5/sections.html#sections">Sections HTML5</a>, Illustrator capable d’exporter les images en SVG ou Canvas via un <a href="http://visitmix.com/labs/ai2canvas/" class="broken_link">plugin</a>. L’apparition de nouveaux outils comme <a href="http://labs.adobe.com/downloads/wallaby.html">Wallaby</a> confirme cette stratégie permettant aux éditeurs Flash de convertir leurs animations en HTML5 (ciblé bannières publicitaires pour compatibilité iPhone, iPad, etc.), mais aussi de futurs outils à surveiller comme le projet appelé <a href="http://tv.adobe.com/watch/adc-presents/preview-of-the-edge-prototype-tool-for-html5-/">“EDGE prototype”</a> dont l’objectif est de fournir un outil dédié à la construction d’animations orientées timeline, entièrement HTML5 et Javascript, en partenariat avec JQuery. <strong>Flash reste dans cette vision la plateforme pour les fonctionnalités innovantes : Peer to Peer, collaboration ou encore 3D</strong> (<a href="http://labs.adobe.com/technologies/flashplatformruntimes/incubator/features/molehill.html">Molehill</a> par exemple).</p>
<h2>L’intégration reste un sujet d’actualité (et c’est pas près de s’arrêter avec le Cloud&#8230;)</h2>
<p>Les frameworks légers type <a href="http://qconlondon.com/dl/qcon-london-2011/slides/JamesStrachan_TakeARideOnCamel.pdf">Camel</a>, Spring Integration sont massivement utilisés notamment dans des contextes financiers à très fortes contraintes. <strong><a href="http://qconlondon.com/dl/qcon-london-2011/slides/JohnDavies_LargeScaleIntegrationinFinancialServices.pdf">John Davies</a> nous a fait une magnifique explication de leur plateforme d’échange qui gère du multi-format, multi-version, du routage et de la conversion FIX, FpML, SWIFT à un niveau de performance impressionnant : 100 000 req/sec avec une latence &lt; 10 ms</strong>. Il est clair que la notion <a href="http://en.wikipedia.org/wiki/Canonical_Model">Canonical Model</a> a été bien challengé au profit d’un pattern qu’il appelle Integration Object. L’idée est en somme de gérer le routage et la mapping directement en Java (notamment via Jaxen, Saxonica&#8230;) et la persistence dans un cache type Coherence ou Gigaspace. <strong>En somme de l’ESB ultra léger sur un Data Grid</strong>.</p>
<p><strong>Côté exposition de service, l’actualité est largement et encore tournée vers REST</strong>. Les maîtres mots étaient <a href="http://qconlondon.com/dl/qcon-london-2011/slides/TimEwald_UsingHypermediaServicesForSystemIntegration.pdf">contrat minimaliste, souple, plutôt clé/valeur</a>. Le principe REST de navigabilité des ressources trouve une utilisation dans la définition de workflow à travers l’implémentation du système Hypermedia (<a href="http://qconlondon.com/dl/qcon-london-2011/slides/TimEwald_UsingHypermediaServicesForSystemIntegration.pdf">ici</a> et <a href="http://qconlondon.com/dl/qcon-london-2011/slides/BrianSletten_BuildingBestBuysBBYOpenRESTfulCommerceEngine.pdf">ici</a>)</p>
<p>Voilà ce que nous avions envie de retenir. Après comme dit l’autre :</p>
<blockquote><p>“Prediction is very difficult difficult, especially about the future.”<br />
Niels Bohr</p></blockquote>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=20826" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/trois-jours-a-qcon-london-2010-tendances-et-confirmations/' rel='bookmark' title='Trois jours à QCon London 2010 : Tendances et Confirmations'>Trois jours à QCon London 2010 : Tendances et Confirmations</a></li>
<li><a href='http://blog.octo.com/passer-du-shell-a-puppet/' rel='bookmark' title='Passer du shell à Puppet'>Passer du shell à Puppet</a></li>
<li><a href='http://blog.octo.com/coffre-fort-archivage-electronique-beaucoup-de-similarites-et-une-difference-structurelle/' rel='bookmark' title='Coffre fort &amp; archivage électronique : beaucoup de similarités et une différence structurelle'>Coffre fort &#038; archivage électronique : beaucoup de similarités et une différence structurelle</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/qcon-london-2011-un-peu-de-process-beaucoup-darchitecture-et-de-la-performance-pour-passer-a-lechelle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exemple d&#8217;infrastructure MongoBD : haute disponibilité en lecture</title>
		<link>http://blog.octo.com/exemple-dinfrastructure-mongobd-haute-disponibilite-en-lecture/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=exemple-dinfrastructure-mongobd-haute-disponibilite-en-lecture</link>
		<comments>http://blog.octo.com/exemple-dinfrastructure-mongobd-haute-disponibilite-en-lecture/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 18:20:36 +0000</pubDate>
		<dc:creator>Julien Jakubowski</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Amazon S3]]></category>
		<category><![CDATA[Amazon Web Services]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=19178</guid>
		<description><![CDATA[Imaginons le cas suivant : nous avons une base MongoDB, alimentée exclusivement par des batchs ordonnancés et via un client back office. Les utilisateurs, très nombreux,  y accèdent via une application client-serveur. La consistance ne doit être qu&#8217;in fine (eventually consistent en anglais). Nous avons donc, en gros, 1 accès en écriture pour 10 accès [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/ma-lecture-de-larchitecture-de-percolator-un-composant-du-moteur-de-recherche-google/' rel='bookmark' title='Ma lecture de l&#8217;architecture de Percolator : un composant du moteur de recherche Google'>Ma lecture de l&#8217;architecture de Percolator : un composant du moteur de recherche Google</a></li>
<li><a href='http://blog.octo.com/portails-une-lecture-fonctionnelle/' rel='bookmark' title='Portails, une lecture fonctionnelle'>Portails, une lecture fonctionnelle</a></li>
<li><a href='http://blog.octo.com/la-programmation-haute-performance-nest-elle-reservee-qua-une-elite-de-developpeurs-c/' rel='bookmark' title='La programmation haute performance n&#8217;est-elle réservée qu&#8217;à une élite de développeurs C++ ?'>La programmation haute performance n&#8217;est-elle réservée qu&#8217;à une élite de développeurs C++ ?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fexemple-dinfrastructure-mongobd-haute-disponibilite-en-lecture%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Exemple%20d%27infrastructure%20MongoBD%20%3A%20haute%20disponibilit%C3%A9%20en%20lecture%22%20%7D);"></div>
<p>Imaginons le cas suivant : nous avons une base MongoDB, alimentée exclusivement par des batchs ordonnancés et via un client back office. Les utilisateurs, très nombreux,  y accèdent via une application client-serveur. La consistance ne doit être qu&#8217;<a href="http://en.wikipedia.org/wiki/Eventual_consistency">in fine</a> (eventually consistent en anglais). Nous avons donc, en gros, 1 accès en écriture pour 10 accès en lecture. Quelle architecture pourrions-nous mettre en place pour assurer la haute disponibilité de notre base de données et  donc nous prévenir de risques comme la perte d&#8217;un disque dur ? Comment pourrions-nous nous prémunir facilement contre une corruption et donc adresser la problématique de back up ? Je vais essayer de vous proposer une réponse unique à ces deux questions, en utilisant les fonctionnalités natives de MongoDB alliées aux possibilités offerte par l&#8217;utilisation des services proposés par Amazon Web Services&#8230;</p>
<p><span id="more-19178"></span></p>
<h1>Préambule</h1>
<h2>MongoDB en détail</h2>
<p>MongoDB est une base données &laquo;&nbsp;NoSQL&nbsp;&raquo; de type documentaire. Chaque document est stocké sous un format proche du JSON (le &laquo;&nbsp;BSON&nbsp;&raquo;), dans une collection. Chaque collection est situé dans une base. Un serveur MongoDB expose une ou plusieurs bases.</p>
<p>La particularité fonctionnelle de MongoDB est de pouvoir créer des index, simples ou composites, sur certains attributs de nos documents, et ce, même s&#8217;il n&#8217;existe pas de schéma. De plus, elle propose un système de requête à base de javascript très simple à la prise en main.</p>
<p>Si vous souhaitez creuser l&#8217;utilisation de MongoDB,  je vous conseille de jeter un oeil à <a href="http://blog.xebia.fr/2010/12/15/mongodb-en-pratique/">cet article.</a></p>
<h2>Exemple de cas d&#8217;utilisation</h2>
<p>Un cas d&#8217;utilisation de ce genre d&#8217;infrastructure pourrait être  la mise en place d&#8217;un moteur de recherche sur des données de sources multiples et variées. Notre infrastructure sert à agréger le contenu, à l&#8217;exposer à un moteur de recherche puis à l&#8217;affichage des résultats de requêtes utilisateurs.</p>
<h1>Architecture</h1>
<div id="attachment_20966" class="wp-caption aligncenter" style="width: 1346px"><a href="http://blog.octo.com/wp-content/uploads/2011/03/mongo_hd_read_macro.jpg"><img class="size-full wp-image-20966" title="Architecture globale" src="http://blog.octo.com/wp-content/uploads/2011/03/mongo_hd_read_macro.jpg" alt="" width="1336" height="291" /></a><p class="wp-caption-text">Architecture globale</p></div>
<div id="attachment_21148" class="wp-caption aligncenter" style="width: 1473px"><a href="http://blog.octo.com/wp-content/uploads/2011/03/mongo_hd_read1.jpg"><img class="size-full wp-image-21148" title="mongo_hd_read" src="http://blog.octo.com/wp-content/uploads/2011/03/mongo_hd_read1.jpg" alt="En détail..." width="1463" height="496" /></a><p class="wp-caption-text">En détail...</p></div>
<p>La chaîne complète fait intervenir deux environnements: un environnement de pré-traitement, sur lequel se feront les écritures et un environnement &laquo;&nbsp;frontal&nbsp;&raquo; sur lequel se feront les lectures. Les deux fonctionnent en isolation (d&#8217;où la nécessité de deux bases maîtres), le lien étant assuré à l&#8217;aide d&#8217;un batch de synchronisation. Ce découpage nous permet de concentrer toutes les opérations d&#8217;écritures, plus ou moins complexes et donc plus ou moins gourmandes en mémoire et en CPU sur un seul serveur sans impacter la charge en lecture, alors qu&#8217;elles se font 24 heures sur 24. Et vice-versa, la charge en lecture (24/24, plusieurs hit/s) n&#8217;impactera pas les calculs nécessaires aux opérations d&#8217;écriture.  L&#8217;intégralité des écritures se font sur la base maître du &laquo;&nbsp;pré-traitement&nbsp;&raquo; alors que l&#8217;intégralité des lectures se font sur les esclaves du &laquo;&nbsp;frontal&nbsp;&raquo;. Enfin, un problème lors de l&#8217;intégration des batchs (maître KO, corruption) n&#8217;entrainera pas d&#8217;impact sur l&#8217;accès en lecture, assurant toujours un niveau de haute disponibilité.</p>
<h2>Pré traitement</h2>
<p>Dans cet environnement, différents batchs ordonnancés alimentent une base MongoDB, à l&#8217;aide de données en provenance de services distants et de fichiers. La base MongoDB est répliquée afin de faire face à d&#8217;éventuels crashs et de permettre la mise en place d&#8217; un système de sauvegarde sans impacter les opérations d&#8217;écritures (voir plus bas). En effet, en cas de corruption de notre base, cette corruption sera répliquée sur l&#8217;esclave. Il est donc nécessaire d&#8217;avoir une sauvegarde quotidienne afin d&#8217;éviter d&#8217;avoir à rejouer l&#8217;intégralité des batchs. De même, on peut se servir de cette sauvegarde pour alimenter le serveur maître de l&#8217;environnement frontal.</p>
<h2>Frontaux</h2>
<p>Cet environnement est découpé en plusieurs couches. La première consiste en un serveur maître et un premier esclave. Le maître sert exclusivement à la synchronisation avec le pré traitement, afin d&#8217;éviter que la synchronisation n&#8217;impacte la lecture. L&#8217;esclave permet de mettre en place un mécanisme de fail over si le maître venait à crasher. On ferait basculer la synchronisation des autres esclaves vers celui-ci (après l&#8217;avoir transformé en maître), ainsi que la synchronisation pré-traitement/frontal.</p>
<p>Les autres esclaves servent à l&#8217;exposition des données. Le load balancer aura pour tâche de rediriger les accès sur l&#8217;un ou l&#8217;autre de ces esclaves.</p>
<h2>Et pourquoi pas un Replica Set ?</h2>
<p>MongoDB propose un autre mécanisme de réplication, nommé <a href="http://www.mongodb.org/display/DOCS/Replica+Sets">Replica Set</a>. Celui-ci permet de mettre en place un mécanisme de fail over automatique et de load balancing (sur l&#8217;écriture) et donc réduit le temps de bascule et d&#8217;indisponibilité et améliore les performances. Les serveurs élisent entre eux le Maître. Si celui-ci tombe, une nouvelle élection à lieu pour qu&#8217;il soit remplacé. Nous aurions donc pu remplacer l&#8217;architecture maître/esclave de notre environnement frontal par celle-ci.</p>
<p>Toutefois, la possibilité de se connecter à un tel montage n&#8217;est pas supporté par tous les drivers de langage disponibles (d&#8217;après une étude que nous avons fait sur le projet auquel je participe, PHP et Ruby ne le supporte pas à 100%) et c&#8217;est relativement complexe à mettre en place. Dans notre cas, cela ne semble pas forcément approprié, n&#8217;ayant pas besoin de fail over automatique. En effet si notre maître frontal tombe, les esclaves sont toujours accessibles en lecture et il n&#8217;est nécessaire qu&#8217;il ne redevienne accessible qu&#8217;au moment de la synchronisation entre pré traitement et frontal.</p>
<h1>Mise en place</h1>
<h2>Réplication</h2>
<p>Comment mettre en place nos deux groupes de master/slave, en pré-traitement et en frontal ? MongoDB propose un mécanisme <a href="http://www.mongodb.org/display/DOCS/Replication">natif et asynchrone </a>pour cela.</p>
<h3>Master</h3>
<p>Pour démarrer un serveur maître, rien de plus simple ! Dans le répertoire <em>bin</em> de votre version de MongoDB, lancer la commande suivante :<br />
<code>mongod --master [--dbpath "emplacement de vos fichiers BSON"]</code></p>
<p>Grâce à l&#8217;argument &#8211;master, notre instance de Mongo générera un journal de transaction, qui pourra être consommé par les différentes bases esclaves.  Ceux-ci, chaque seconde, vérifient s&#8217;il y a eu une nouvelle écriture, et, le cas échéant, la reproduisent. Attention toutefois, ce journal a une taille limitée. Par défaut, il est de 5% de l&#8217;espace disque libre, avec un minimum de 1Go pour une machine de 64 bits, mais seulement 50 Mo pour une machine 32 bits. Toutefois, si  nous voulons gérer nous même la taille du journal (par exemple 500 Mo), nous pouvons lancer notre serveur maître avec la commande suivante :<br />
<code>mongod --master --oplogSize 500 [--dbpath "emplacement de vos fichiers BSON"]</code></p>
<p>Cela peut être nécessaire dans le cas de réplications trop lentes par rapport aux nombres de commandes exécutées sur le maître. Dans notre cas, étant sur un serveur 64 bit, la valeur par défaut nous semble suffisante.</p>
<h3>Slave</h3>
<p>Démarrer un serveur esclave est presque tout aussi simple qu&#8217;un serveur maître. Cela se fait via cette commande :<br />
<code>mongod --slave --source "master_host"[:"master_port"] </code><code>[--dbpath "emplacement fichiers BSON de l'esclave"]</code></p>
<p>Si nous ne renseignons pas le port du maître, l&#8217;esclave essayera de s&#8217;y connecter sur le port 27017 par défaut. Attention, si nous tenons de lancer un esclave sur le même serveur que le maître,  il ne faut pas oublier d&#8217;utiliser l&#8217;option &#8211;port &laquo;&nbsp;nouveau-port&nbsp;&raquo; dans la commande de lancement de notre esclave.</p>
<p>Il est possible de créer autant d&#8217;esclave que l&#8217;on souhaite pour un seul maître. Toutefois, d&#8217;après la documentation officielle, au delà d&#8217;une dizaine, les performances de réplication ne risquent plus d&#8217;être au rendez-vous. De plus, il n&#8217;est pas possible de faire de la réplication d&#8217;esclave à esclave, du fait de l&#8217;absence de journal de transaction.</p>
<p>Chaque esclave va récupérer en temps réel chaque écriture du journal de transaction du maître. Néanmoins, dans le cas où la consistance entre le maître et le ou les esclave n&#8217;est pas prioritaire, il est possible de créer un délai entre chaque scrutation du journal grâce à l&#8217;option &#8211;slavedelay. Par défaut, celui-ci est d&#8217;une seconde. Par exemple, pour un délai d&#8217;une minute, la commande serait :<br />
<code>mongod --slave --source "master_host"[:"master_port"] --slavedelay 60 </code><code>[--dbpath  "emplacement fichiers BSON de l'esclave"]</code></p>
<p>A l&#8217;opposé, il peut arriver qu&#8217;un esclave ne soit plus synchronisé  avec son maître (KO durant un certain temps par exemple) et synchronisable (le journal de transaction a déjà flushé certaines opérations depuis le KO de l&#8217;esclave). Pour éviter ce genre de problème, il est nécessaire de lancer l&#8217;esclave avec l&#8217;option &#8211;autoresync.  L&#8217;esclave copiera alors l&#8217;intégralité du contenu du maître s&#8217;il est désynchronisé. Attention toutefois à votre volume de donnée.  Cette opération peut être dans ce cas relativement couteuse pour la maître et l&#8217;esclave.  Il est donc important de bien définir la taille du journal de transaction pour éviter un maximum un état de désynchronisation de l&#8217;esclave.</p>
<p>Enfin, pour revenir à notre architecture initiale, il faut rendre nos esclaves accessibles en lecture. En effet, ceux-ci n&#8217;acceptent aucune requête par défaut. Pour ce faire, il est nécessaire d&#8217;utiliser une dernière option, seulement activable via le shell mongo.  Lancer donc tout d&#8217;abord le shell sur votre serveur esclave.<br />
<code>mongo --host "mon_esclave"</code><br />
Puis, entrez les commandes suivantes :<br />
<code>use admin<br />
db.getMongo().setSlaveOk()</code></p>
<h2>Synchronisation base de pré-traitement / base front office</h2>
<p>Comment synchronisez notre environnement de pré-traitement avec celui de front office ? L&#8217;utilisation d&#8217;un batch faisant un simple dump du pré-traitement pour ensuite l&#8217;intégrer au maître &laquo;&nbsp;frontal&nbsp;&raquo; semble être la solution la plus simple avec MongoDB. Voici en détail comment cela se met en place.</p>
<h3>Dump</h3>
<p>MongoDB permet de gérer très simplement les actions de sauvegarde et de restauration, en local ou à distance.  Dans le cas de notre serveur de pré-traitement, il suffit de se mettre dans le répertoire /bin de votre installation de MongoDB et de rentrer la commande suivante pour faire une sauvegarde :<br />
<code>mongodump --host "mon_serveur_de_staging"</code></p>
<p>Ce dump aura la forme d&#8217;un répertoire &laquo;&nbsp;dump&nbsp;&raquo; contenant autant de répertoire que de base (dont un pour la base contenant les informations d&#8217;administration),  contenant chacun un fichier BSON par collection, plus un fichier BSON d&#8217;index. L&#8217;arborescence pourrait avoir cet aspect là :</p>
<p><code>dump<br />
--base1<br />
----collection1.bson<br />
----collection2.bson<br />
----system.indexes.bson<br />
--base2<br />
----collection3.bson<br />
----system.indexes.bson<br />
--admin</code></p>
<p>Dans notre cas d&#8217;étude,  notre serveur n&#8217;étant alimenté que par des batchs, il est aisé de savoir si des actions d&#8217;écriture sont en cours ou non. Dans le cas contraire, il est nécessaire de &laquo;&nbsp;flusher&nbsp;&raquo; toute les actions d&#8217;écriture en cours et d&#8217;empêcher qu&#8217;il y en ait d&#8217;autres.  Toutefois, si on ne veut pas faire tomber nos batchs en erreur, il faut, dans ce genre de cas penser à répliquer le serveur de pré traitement et faire le dump sur le répliqua. Quoi qu&#8217;il en soit, pour réaliser ces actions, il faut  lancer le shell:<br />
<code>mongo --host "répliqua_de_mon_serveur_de_pretrairement"</code><br />
Puis lancer les commandes suivantes :<br />
<code>use admin<br />
db.runCommand({"fsync" : 1, "lock" : 1})</code></p>
<p>Vous l&#8217;aurez compris,  &laquo;&nbsp;fsync&nbsp;&raquo; force le flush, et &laquo;&nbsp;lock&nbsp;&raquo; verrouille notre base. Les &laquo;&nbsp;1&#8243; ne servent qu&#8217;à indiquer le lancement des commandes. Ensuite, il ne reste plus qu&#8217;à lancer le dump sur le répliqua.</p>
<p>Pour déverrouiller la base, toujours dans le shell, il faut lancer les commandes suivantes:<br />
<code>use admin<br />
db.$cmd.sys.unlock.findOne()</code></p>
<h3>Restore</h3>
<p>Une fois le dump produit, il ne nous reste plus qu&#8217;à faire l&#8217;action de restauration sur le serveur maître de notre ferme de serveurs frontaux. Il est toutefois nécessaire d&#8217;assurer l&#8217;intégrité de notre base à l&#8217;issue de cette commande. Pour ce faire, il faut associer 2 options au lancement de votre commande. La première, &#8211;drop, supprimera tout le contenu de notre serveur d&#8217;arrivée. Cela évite d&#8217;avoir de la duplication de donnée, des conflits d&#8217;ids. La seconde, &#8211;indexesLast,  forcera la création des indexes seulement une fois le contenu de vos différentes bases et collections inséré. Cela permet de se prémunir d&#8217;une mauvaise indexation. Au final, voici la commande qu&#8217;il faut lancer, dans le répertoire bin de votre installation de MongoDB:<br />
<code>mongorestore --dbpath "mon_master_frontal"  --drop --indexesLast "chemin_vers_mon_repertoire_dump"</code></p>
<h3>Limitations</h3>
<p>Ce mode de synchronisation offre toutefois de grosses limitations dans la cadre de bases très volumineuses (plusieurs centaines de milliers de documents) et répliquées. On a pu observer des chutes de performances importantes, voire une impossibilité de solliciter nos bases pendant près d&#8217;une heure, le temps que la restauration puis la synchronisation soit terminée. Il est donc nécessaire de limiter la fréquence de ces actions, si c&#8217;est le mode de fonctionnement qui est utilisé</p>
<p>Finalement, dans notre cas, nous avons décidé d&#8217;utiliser une synchronisation par delta, où nous ne poussons vers le serveur frontal que les données qui ont été mises à jour sur le pré-traitement. MongoDB ne permettant pas nativement un tel mode fonctionnement (ne serait qu&#8217;un dump par delta), nous avons dû le faire de façon programmatique. Pour cela, nous avons créé un batch, qui extrait du serveur de pré traitement les données modifiées  depuis son dernier lancement,  identifiées grâce à un timestamp, pour ensuite transmettre les modifications vers le maître des serveurs frontaux. Grâce à ce mode de fonctionnement, nous pouvons maintenir une fréquence élevée de synchronisation (plusieurs fois par jours), sans chute de performance.</p>
<h2>Sauvegarde</h2>
<p>Afin de se prémunir de toute corruption des données, notamment en pré traitement, il est nécessaire mettre en place des mécaniques de rejeux de nos batchs et de sauvegarde de nos bases.  Nous  avons décidé de traiter ces deux problématiques à l&#8217;aide d&#8217;un bucket S3 loué à Amazon. Cela nous permet de nous assurer que le taux de perte de fichiers soit proche du 0%. Voici les différentes mécaniques associées.</p>
<h3>Rejeux</h3>
<p>Afin de pouvoir rejouer nos batchs de pré-traitement, toutes nos données disponibles sous forme de fichier sont disposées sur le bucket S3. Chaque batch y scrute un répertoire qui lui est alloué pour récupérer les données qu&#8217;il doit insérer. Je vous propose  de pousser la donnée manuellement à l&#8217;aide d&#8217;un plug in firefox, <a href="http://www.s3fox.net/">S3Fox Organizer</a>. Nos batchs, quant à eu, récupéreront ses fichiers via l&#8217;outil en ligne de commande <a href="http://s3tools.org/s3cmd">S3cmd</a>.</p>
<p>Pour récupérer un fichier par exemple, lançons la commande :<br />
<code>s3cmd get s3://"mon_bucket"/"mon_batch"/"mon_fichier"</code></p>
<h3>Back up</h3>
<p>Pour ne pas avoir à réintégrer l&#8217;intégralité des données fournis par les différents batchs, le mieux reste de sauvegarder régulièrement la base de pré-traitement. Pour ce faire, faisons régulièrement un &laquo;&nbsp;dump&nbsp;&raquo; sur le répliqua,  puis sauvegardons le sur le bucket.</p>
<p>Pour ce faire, il n&#8217;y qu&#8217;à utiliser S3cmd et la ligne de commande suivante :<br />
<code>s3cmd put staging_dump.tar.gz s3://"mon_bucket"/"mon_répertoire_de_sauvegarde"</code></p>
<h1>Conclusion</h1>
<p>J&#8217;espère avoir pu vous montrer qu&#8217;il est très facile de réaliser ce cas d&#8217;étude avec MongoDB, un peu de programmation et une petite aide d&#8217;Amazon. Bien sûr, cette architecture n&#8217;est valable qu&#8217;à 3 conditions:</p>
<ul>
<li>Notre modèle de donnée est adapté à un stockage documentaire. Dans le cas contraire, il vaut mieux étudier une autre solution NoSQL ou une base de données relationnelles classique</li>
<li>La sollicitation en écriture ne nécessite pas une haute disponibilité. Dans le cas contraire, il faudrait étudier une solution à base de replica set, permettant un fail over automatique (avec les limitations que cela implique sur les technologies permettant de s&#8217;y connecter).</li>
<li>Le volume de données d&#8217;une collection nous permet d&#8217;avoir des temps de traitement correct lors de l&#8217;agrégation. Si ce volume venait à augmenter drastiquement et que les temps d&#8217;agrégation en entrée devenaient trop long,  il faudrait envisager une architecture à base de sharding, ce que propose nativement MongoDB.</li>
</ul>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=19178" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/ma-lecture-de-larchitecture-de-percolator-un-composant-du-moteur-de-recherche-google/' rel='bookmark' title='Ma lecture de l&#8217;architecture de Percolator : un composant du moteur de recherche Google'>Ma lecture de l&#8217;architecture de Percolator : un composant du moteur de recherche Google</a></li>
<li><a href='http://blog.octo.com/portails-une-lecture-fonctionnelle/' rel='bookmark' title='Portails, une lecture fonctionnelle'>Portails, une lecture fonctionnelle</a></li>
<li><a href='http://blog.octo.com/la-programmation-haute-performance-nest-elle-reservee-qua-une-elite-de-developpeurs-c/' rel='bookmark' title='La programmation haute performance n&#8217;est-elle réservée qu&#8217;à une élite de développeurs C++ ?'>La programmation haute performance n&#8217;est-elle réservée qu&#8217;à une élite de développeurs C++ ?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/exemple-dinfrastructure-mongobd-haute-disponibilite-en-lecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scribe, Chukwa&#8230;des collecteurs permettant d&#8217;alimenter le HDFS</title>
		<link>http://blog.octo.com/scribe-chukwa-des-collecteurs-permettant-dalimenter-le-hdfs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=scribe-chukwa-des-collecteurs-permettant-dalimenter-le-hdfs</link>
		<comments>http://blog.octo.com/scribe-chukwa-des-collecteurs-permettant-dalimenter-le-hdfs/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 21:15:00 +0000</pubDate>
		<dc:creator>Olivier Mallassi</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[HDFS]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Scribe]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=19018</guid>
		<description><![CDATA[HDFS, que nous avons déjà évoqué, reste un système de fichier distribué et il faut donc l&#8217;alimenter. Il y existe plusieurs options : à la manière batch. La première option est donc de continuer à collecter les données sur un système de fichier local et de les importer sur le HDFS par vacation. La seconde [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/hdfs-hadoop-co/' rel='bookmark' title='HDFS, Hadoop &amp; co&#8230;'>HDFS, Hadoop &#038; co&#8230;</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fscribe-chukwa-des-collecteurs-permettant-dalimenter-le-hdfs%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Scribe%2C%20Chukwa...des%20collecteurs%20permettant%20d%27alimenter%20le%20HDFS%22%20%7D);"></div>
<p>HDFS, que nous <a href="http://blog.octo.com/en/tag/hdfs/">avons déjà évoqué</a>, reste un système de fichier distribué et il faut donc l&#8217;alimenter. Il y existe plusieurs options : </p>
<ul>
<li>à<strong> la manière batch</strong>. La première option est donc de continuer à collecter les données sur un système de fichier local et de les importer sur le HDFS par vacation. La seconde option serait d&#8217;utiliser un ETL. Pentaho a annoncé le support de Hadoop pour sa solution Data Integration Product. Les premiers tests que l&#8217;on a réalisé nous montre que cela fonctionne mieux pour extraire de la donnée du HDFS (via Hive) que pour l&#8217;importer (après, ce n&#8217;est certainement qu&#8217;une question de temps avant que Pentaho fasse le nécessaire). La troisième option serait d&#8217;utiliser <a href="http://www.cloudera.com/downloads/sqoop/">Sqoop</a>. Sqoop permet d&#8217;extraire ou d&#8217;importer des données depuis votre RDBMS en utilisant un algorithme de Map/Reduce.
</li>
<li>
<strong>à la manière &laquo;&nbsp;fil de l&#8217;eau&nbsp;&raquo;</strong>. Dans ce domaine, les solutions se prénomment Flume, Chukwa (qui fait partie du projet Apache Hadoop) ou Scribe. En somme, vous collectez et aggréger des données, de différentes sources, différentes applications, différentes machines &laquo;&nbsp;au fur et à mesure&nbsp;&raquo;. Toutes ces solutions fonctionnent globalement de la même manière. On peut cependant noter que Flume ou Chukwa proposent une typologie de connecteurs plus riches que Scribe dans la mesure ou par exemple, il est possible de ce connecter en &laquo;&nbsp;tail&nbsp;&raquo; sur un fichier etc, etc&#8230;Chukwa est également plus simplement intégrable avec la stack Hadoop que ce que peut l&#8217;être Scribe. </li>
</ul>
<p>Reste que c&#8217;est <a href="https://github.com/facebook/scribe/wiki">Scribe</a>, massivement <a href="http://www.facebook.com/note.php?note_id=32008268919">utilisé chez Facebook</a>, que nous allons décortiquer <a href="http://blog.octo.com/en/scribe-a-way-to-aggregate-data-and-why-not-to-directly-fill-the-hdfs">dans cette article (en anglais)</a>&#8230;</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=19018" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/hdfs-hadoop-co/' rel='bookmark' title='HDFS, Hadoop &amp; co&#8230;'>HDFS, Hadoop &#038; co&#8230;</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/scribe-chukwa-des-collecteurs-permettant-dalimenter-le-hdfs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

