Accueil » Java, Perso, Startup

Zaptravel

5 août 2012 1 667 affichages 9 commentaires

Depuis début mai, après avoir co-organisé Devoxx France avec 3 autres fous, j’ai d’abord pris quelques jours de vacances, avant de rejoindre Zap Travel, une startup basée à Paris. Il s’agit d’une jeune entreprise créé par un entrepreneur australien, Andrew Lacy, ancien COO de Tapulous. Cette société a été l’une des premières à développer des jeux en 2008 pour iphone. L’un des jeux, Tap-Tap Dance, a été téléchargés à plus de 15 millions d’exemplaires. Imaginez aussi qu’à l’époque la taille du nombre d’appareils iOS n’était pas aussi important qu’aujourd’hui. Le groupe Disney a racheté la société en 2010, et Andrew est en France depuis quelques mois.

Zap Travel c’est le concept de la startup américaine… mais en plein coeur de Paris. Sans dévoiler pour l’instant toutes les idées, nous sommes en plein coeur de ce qui est « Big Data » et « Realtime Web Application ». Depuis quelques temps je travaille avec Play2, et plus particulièrement avec Scala. Il m’a fallut quelques semaines pour vraiment apprécier la puissance et les capacités de Play2. J’en vois aussi les usages, et je pourrais aussi vous donner un avis d’un gars qui fait « une vraie application dans la vraie vie ».

Alors nous faisons une vraie application sur un vrai projet. Aujourd’hui le système que nous avons développé s’appuie entre autre sur un serveur Redis avec environ 500 000 clés. Et croyez-moi, pour Redis, c’est très petit. Le tout tient en moins de 1Go en mémoire, et permet à notre application Play2 de construire en temps réel des packages. Le premier proto sur MySQL demandait 80 ms pour calculer un voyage, alors que la dernière version effectue le calcul et la génération en 11ms. Mais pour que tout ceci soit exploité, il a fallut se relever les doigts des manches… euh pardon, se relever les manches…

Redis (dont le nom vient de REmote DICtionary) est un système clé-valeur stockées en mémoire, ultra performant. C’est un serveur de données structurées, qui sauvegarde aussi sur disque selon différentes stratégies son contenu, afin de ne pas perdre bien entendu de données. Nous nous appuyons sur une méga base MySQL pour tout ce qui est données plus ou moins statiques, mais la partie Web de notre application n’utilise presque pas de base SQL. Bref www.zaptravel.com, que vous pourrez tester à la fin de l’été, s’appuie sur play2+scala+Akka+redis. Et c’est presque tout pour l’instant.

Comparé à MongoDB, Redis n’a pas d’outils d’administration aussi puissant, mais propose un modèle de programmation plus simple. Côté Mongo, j’ai été un peu déçu par la partie cliente et la façon de programmer. J’ai trouvé que Redis était plus efficace et plus pratique, mais cela correspond aussi à notre use-case. Redis ne dispose pas d’un moteur de requêtage contrairement à MongoDB, ce qui veut dire que votre adressage de clé doit être parfaitement pensé. Au final cela nous force à vraiment optimiser nos clés, et nous nous en portons pas plus mal. La mise en place d’une réplication master-slave est aussi tellement simple, qu’il ne faut que quelques secondes pour avoir une copie de notre base sur nos MacBook Pro de développement.

Le coeur de Redis est similaire à l’architecture de Node.JS avec une architecture mono-threadé. C’est un serveur, donc rien à voir avec un système en mémoire embarquée comme Tokyo Cabinet . Redis fonctionne en mode client-serveur, chaque commande est acquitée, là où par exemple MongoDB fonctionne en mode « fire-and-forget » lorsqu’il s’agit d’écrire. Lorsque vous faîtes un « SET myKey myVal » et que Redis vous répond, vous êtes certain que votre clé est stockée. Vous pouvez pipeliner plusieurs instructions et vous pouvez aussi embarquer des opérations dans une transaction, afin que la suite de commandes soit exécuté de manière atomique.

Voici par exemple un benchmark avec 10 000 clés sur mon Macbook pro, Intel Core i7 2.3Ghz avec 8 coeurs, 8Go de Memoire DDR3 et os 64-bits :

nicolas@macbook (master):~/Dev/Play/DevPlay2/play2-redxplay> redis-benchmark -q -n 100000
PING_INLINE: 77942.32 requests per second
PING_BULK: 76745.97 requests per second
SET: 77639.75 requests per second
GET: 89766.61 requests per second
INCR: 71174.38 requests per second
LPUSH: 76394.20 requests per second
LPOP: 77700.08 requests per second
SADD: 75642.96 requests per second
SPOP: 74571.22 requests per second
LPUSH (needed to benchmark LRANGE): 42918.46 requests per second
LRANGE_100 (first 100 elements): 16758.84 requests per second
LRANGE_300 (first 300 elements): 8101.10 requests per second
LRANGE_500 (first 450 elements): 6066.86 requests per second
LRANGE_600 (first 600 elements): 4415.60 requests per second
MSET (10 keys): 30478.51 requests per second

Comme vous le voyez, un GET, qui correspond à une lecture, monte à 89 000 requêtes par seconde, ce qui est plutôt efficace.

Redis fonctionne d’abord en mémoire, et propose différentes stratégies pour sauvegarder son contenu dans un fichier. Vous pouvez avoir la même solidité qu’une base MySQL, voire même faire mieux que MySQL, en activant différentes propriétés.

Un point commun avec Node.JS, c’est que Redis est un serveur mono-threadé. Si vous souhaitez bénéficier de votre architecture muli core, il faut donc en démarrer plusieurs. Personnellement cela ne me choque pas. Le design de l’application est tellement simple et puissant, et s’agissant d’un serveur, il est logique que la gestion du multi-coeur soit effectué simplement avec plusieurs processus. Redis est écrit en C /C++, et dispose de beaucoup de drivers, simple à utiliser et à mettre en oeuvre. Ecrire une application avec Redis est même plus simple que de travailler avec une base MySQL, surtout avec Play2 et Anorm. Notre code est plus léger, et plus simple.

Les tests unitaires aussi sont intéressants. Au lieu de mocker Redis, comme une vulgaire base MySQL, il suffit de lancer ses tests sur un autre catalogue, de jouer ses tests sur un vrai serveur Redis, et ensuite de flusher le catalogue, une fois que le test est terminé. Bref de vrais tests d’intégration qui dépotent. Et ça, c’est cool.

Voilà pour Redis, je vais vous parler ensuite de Play2 et de ce que Sadek Drobi appelle « Realtime Web Application ».

A toute de suite sur la deuxième chaîne.

9 commentaires »

  • Sam B. a dit:

    Excellent le retour.
    Et sinon le passage dans un mode pure lean startup, ça donne quoi, en comparaison avec tes expériences antérieures?

  • nire a dit:


    Antirez déteste C++ il me semble, t’es sûr de ton coup ?

  • Jeremy a dit:

    Salut,
    vous utilisez quoi comme client Redis ?
    Sedis ?

  • Nicolas Martignole (author) a dit:

    En effet c’est du pur C, je corrige

  • Sebastien Lorber a dit:

    « Redis fonctionne en mode client-serveur, chaque commande est acquitée, là où par exemple MongoDB fonctionne en mode « fire-and-forget » lorsqu’il s’agit d’écrire.  »

    Pourtant avec les WriteConcern de MongoDB on peut très bien le faire. C’est juste la WriteConcern par defaut qui est en mode « fire-and-forget » mais tu peux très bien utiliser le mode sur lequel tu n’as la réponse que quand ta data est écrite sur n replicas…

    Redis a l’air pas mal par contre si je me souviens bien ils ont pas encore de vrai modèle de sharding même si c’est en cours de développement.
    C’est dommage de faire de la réplication surtout avec de vrais dataset bigdata.
    Je suis pas sur qu’on puisse parler de BigData avec 1Go inmemory, et je me demande comment vous feriez avec Redis si vous aviez 200go par exemple. En attendant le sharding sous Redis, il y a les datagrids dont Hazelcast en gratuit qui font ça très bien il me semble.

  • Nicolas Martignole (author) a dit:

    Un des usages dela replication simple de Redis pour nous : un développeur peut récupérer le dataset automatiquement sur sa machine de développement. Très pratique.

  • DuyHai DOAN a dit:

    « Redis ne dispose pas d’un moteur de requêtage contrairement à MongoDB, ce qui veut dire que votre adressage de clé doit être parfaitement pensé. »

    –> Ca peut être problématique sur le long terme cette limitation. Ayant bossé un peu sur Cassandra (Clé/Valeur aussi) je peux te dire qu’à la fin, mettre un ElasticSearch à côté était quasi obligatoire car on voulait faire des recherches dans tous les sens.

    Mais surtout c’est qu’une fois le design des clés/valeurs fait, assez dûr de tout changer en cours de route parce qu’un nouveau besoin est apparu.

  • Dominique De Vito a dit:

    Il y a un retour d’expérience intéressant ici: http://kev.inburke.com/kevin/reddits-database-has-two-tables/

    Reddit utilise PostgreSQL en mode clé/valeur et un gars de Reddit indique: « Still today I tell people that even if you want to do key/value, postgres is faster than any NoSQL product currently available for doing key/value » (a priori, ils devaient utiliser l’extension hstore de PostgreSQL)