La dernière version de la Data Grid Java en mémoire de Hazelcast supporte l'entry processing, l'exécution multi-threadée, les continuous queries et l'indexation paresseuse. Hazelcast version 3.0, lancée pendant la conférence JavaOne il y a quelques semaines, est celle qui comporte le plus de changements du produit depuis sa création en 2008 et l'effort a nécessité la réécriture de 70 à 80% du code. Ils ont aussi ré-implémenté tous les objets distribués tels que Map, Queue et ExecutorService en utilisant la SPI (Service Provider Interface).
Avec la nouvelle exécution multi-threadée, les opérations sont à présent exécutées par plusieurs threads (en fonction du nombre de coeurs du processeur) qui tirent parti de la scalabilité verticale des machines multi-coeurs. Le nouvelle SPI permet de développer de nouveaux services partitionnés et de nouvelles structures de données.
Les autres fonctionnalités de Hazelcast 3 incluent :
Entry Processing : Une nouvelle fonctionnalité de Hazelcast 3, appelée Entry Processing, permet d'effectuer des opérations rapides, en mémoire, sur une Map sans avoir besoin de se soucier des problèmes de verrous ou de concurrences. L'EntryProcessor est une fonction qui permet de modifier ou de remplacer la valeur de l'entrée d'une Map. Elle peut être appliquée aussi bien à une unique entrée d'une Map qu'à l'ensemble des entrées d'une Map. Les prochaines versions permettrons de sélectionner un ensemble d'entrées à l'aide d'un Predicate, à la manière d'un "rechercher et remplacer". Un EntryProcessor peut être associé à une autre nouvelle fonctionnalité de Hazelcast, le paramètre in-memory-format. Par défaut, la valeur d'une entrée est stockée dans un tableau d'octets (format binary), mais quand elle est stockée en tant qu'objet (format object) l'EntryProcessor est appliqué directement sur l'objet. Une autre fonctionnalité de l'EntryProcessor est qu'il acquiert automatiquement un verrou exclusif sur l'entrée de la Map, sans avoir besoin de se synchroniser pour éviter les erreurs de mises à jour concurrentes.
Serialisation : Hazelcast propose une alternative aux méthodes de sérialisation existantes, un format de sérialisation portable. Ce mode de sérialisation offre certains avantages tels que le support de plusieurs versions du même type d'objets, le support de l'indexation et des requêtes sans déserialisation ni introspection. Il existe aussi une interface IdentifiedDataSerializable, une version légèrement optimisée de DataSerializable, qui n'utilise pas le nom de la classe et l'introspection pour la désérialisation. Hazelcast permet aussi au développeur de brancher un sérialiseur maison pour des objets donnés.
Continuous Query : Cette fonctionnalité permet aux développeurs de configurer des requêtes qui se déclenchent sur n'importe quelles données qui y répondent lors des actions d'ajout/mise à jour/supression/evict. Cette fonctionnalité est mise en oeuvre en utilisant des écouteurs associés à des requêtes qui sont notifiés quand il y a un changement sur une Map qui répond à la requête. Cette fonctionnalité pourrait être utile à des cas d'utilisation tels que le traitement d'événements complexes (Complex Event Processing, CEP) qui nécessite souvent l'utilisation de produits spécifiques.
Indexation paresseuse : Avec la fonctionnalité de Lazy Indexing, les développeurs n'ont plus besoin d'ajouter des index dès le début. Les index peuvent être ajoutés aux entrées à n'importe quel moment.
Transactions distribuées : Hazelcast 3 supporte les transactions distribuées basées sur du two phase commit. La nouvelle API de transactions supporte à la fois les transactions à une phase (locales) et à deux phases.
InfoQ a rencontré Fuad Malikov, co-fondateur de Hazelcast à propos des fonctionnalités de la nouvelle version.
InfoQ : Quelle a été la raison qui vous a amené à ajouter le support des transactions distribuées dans la nouvelle version ? Quel est le fonctionnement avec des data grids en mémoire comparé aux transactions 2PC dans les bases de données relationnelles ? Existe-t-il des limitations à cette fonctionnalité ?
Fuad : Nous sommes beaucoup à l'écoute de la communauté. Les utilisateurs de Hazelcast sont demandeurs d'une possibilité 2PC dans Hazelcast. Ils souhaitent, par exemple, être capables de consommer un item d'une queue distribuée, de le traiter et de sauvegarder l'entrée dans une autre Map distribuée. L'ensemble du processus doit être transactionnel afin que les données non-traitées ne puissent pas être perdues en cas de défaillance d'un noeud.
Hazelcast est une solution entièrement "en mémoire" et, par défaut, elle s'appuie sur une réplication des données sur plusieurs noeuds pour assurer la durabilité. C'est aussi le cas pour l'implémentation du 2PC. Dans la phase de préparation, nous répliquons l'état de la transaction sur plusieurs noeuds.
Dans la prochaine version de Hazelcast, nous serons aussi capables de participer à une transaction XA via JCA avec d'autre ressources telles que JMS ou JDBC.
InfoQ : Pouvez-vous nous expliquer comment fonctionnent les continuous queries, une nouvelle fonctionnalité de Hazelcast 3 ?
Fuad : Il s'agit d'une autre de ces fonctionnalités qui permettent aux gens de réaliser qu'une data grid en mémoire est bien plus qu'un cache. Les Continuous Queries permettent d'apporter la commodité et la puissance du traitement distribué au vieux concept que sont les procédures stockées. En fait, il s'agit plus d'un cousin du paradigme CEP, beaucoup plus moderne. Contrairement aux procédures stockées des bases de données relationnelles, les Continuous Query permettent de conserver la logique applicative proprement, dans le tier applicatif, en Java. Mais elles ont l'avantage d'être extrêmement scalables et de s'assurer que le traitement a lieu à l'endroit ou se trouvent les données, les rendant ainsi très rapides et efficaces.
Notre implémentation des Continous Query combine des événements et notre API Predicate. Hazelcast propose des EntryListeners qui écoutent quand les items sont ajoutés, mis à jours, supprimés ou évincés d'une Map. Dans les versions précédentes, il était possible d'écouter soit l'ensemble des entrées d'une Map soit une clé en particulier. En plus de cela, à l'aide des Continuous Query, vous pouvez définir une requête (Predicate) et les événements seront lancés uniquement si l'entrée concernée répond au prédicat. De cette manière, un listener envoie un flux continu d'événements basés sur une requête.
InfoQ : Quelles sont les nouvelles fonctionnalités et améliorations que les développeurs peuvent attendre de la prochaine version de Hazelcast ?
Fuad : 70 à 80% de Hazelcast a été réécrit pour créer Hazelcast 3, ce qui nous a permis de supporter une importante modularité de l'architecture. Une de ces fonctionnalités qui est rééllement géniale est la Service Provider Interface (SPI). Nous avons modularisé les classes internes à Hazelcast en Networking, Clustering, Partitioning and Services. Et ces classes internes sont exposées à l'aide de la SPI afin que la communauté puisse étendre Hazelcast et développer des structures de données distribuées et des services de traitement. Une autre fonctionnalité majeure est un protocole client portable. Ce protocole permet à n'importe qui d'implémenter un client dans n'importe quel langage. Nous sortirons un client C++ et comptons sur la communauté pour implémenter des clients pour d'autres langages tels que Python ou Ruby.
Hazelcast 3 peut être télécharger sur le site web du produit ; ce produit est sous licence Apache 2.