Your SlideShare is downloading. ×
  • Like
JPA avec Cassandra, grâce à Achilles
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

JPA avec Cassandra, grâce à Achilles

  • 1,145 views
Published

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,145
On SlideShare
0
From Embeds
0
Number of Embeds
18

Actions

Shares
Downloads
19
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. https://github.com/doanduyhai/AchillesJPA avec Cassandra ?Mission pas impossible !1
  • 2. https://github.com/doanduyhai/Achilles• Développeur Java freelance full-stack• Bidouilleur Cassandra, créateur d’Achilles• En mission chez• doanduyhai.wordpress.com• @doanduyhai2Duy Hai DOAN
  • 3. https://github.com/doanduyhai/AchillesAchillesPrésentation3
  • 4. https://github.com/doanduyhai/AchillesAchilles• Framework de persistance JPA pour C*• Support des annotations/opérations JPA• Extensions spécifiques à C*• 2 implémentations : Thrift & CQL3*4
  • 5. https://github.com/doanduyhai/AchillesPourquoi Achilles ?• Voulez-vous écrire ça ?5
  • 6. https://github.com/doanduyhai/AchillesPourquoi Achilles ?• ou ça ?6
  • 7. https://github.com/doanduyhai/AchillesPourquoi Achilles?• Librairies trop bas niveau (Hector, Thrift)• Virage vers SQL avec CQL3 par Datastax• Object mapper nécessaire pour lierentités/requêtes• Concepts JPA: bien connus et maîtrisés7
  • 8. https://github.com/doanduyhai/AchillesMapping d’entités• Annotations JPA– @Entity, @Table– @Id, @EmbededId, @Column, @JoinColumn– @OneToOne, @OneToMany …• Spécifiques à Cassandra– @WideRow– @Consistency– @Key (composite)– @Lazy8
  • 9. https://github.com/doanduyhai/Achilles 9Mapping d’entités@Entitypublic class UserBean@Idprivate Long id;@Columnprivate String name;@Lazy@Columnprivate List<Long> friendIds;@Columnprivate WideMap<UUID, String> tweets;@ManyToOne@JoinColumnprivate UserBean referer;
  • 10. https://github.com/doanduyhai/AchillesTypes spécifiques Cassandra• WideMap<K,V>: miroir d’une column family– KeyValue<K,V>: représente une colonne– KeyValueIterator<K,V>: itérateur• Counter: compteur distribué10puissancealfred batgirl catwoman lois_lane robin1 6 7 1 8WideMap<String,Integer>KeyValue<String,Integer>
  • 11. https://github.com/doanduyhai/Achilles 11Entity Manager• find(Entity.class,pk)– retourne entité « managed » (proxy)• getReference(Entity.class,pk)*– retourne proxy sans chargement initial– peut servir pour du direct-update• persist(entity)– écrase/met à jour toute valeur existante– persist(User(fn,ln,age)) puis persist(User(fn,ln)) ?
  • 12. https://github.com/doanduyhai/AchillesEntity Manager• merge(entity)– dirty check + flush à C*– retourne entité « managed » si transient– entité retournée == entité mergée• remove(entity)– effacer + cascade delete des types de C*• refresh(entity)– recharge l’entité– identique à find()12
  • 13. https://github.com/doanduyhai/AchillesPersistance avec Thrift• Persistance des champs « simples »1310firstname lastname ageDuyHai DOAN 32• Persistance des listes100 1 2 3Java Cassandra Scala Angular JS
  • 14. https://github.com/doanduyhai/Achilles 14Persistance avec Thrift• Persistance des Sets101265231 68754 546546#Cassandra #Achilles #Tatami• Persistance des Maps10113131 6543213 51313 65465464{language:Java} {database:Cassandra} … …
  • 15. https://github.com/doanduyhai/AchillesDirty check• Interception seulement sur getter (internal calls )• Pas d’update atomique des collections/maps• Dirty check des collections/maps coûteux en ThriftImpl– (read + delete) + write pour mettre à jour (pas de slicedelete)– optimisation possible pour Set & Map– list.add(2,peter) ???– faible cardinalité conseillée (10 -20)15friends0 1 2 3 4bob alice john helen richard
  • 16. https://github.com/doanduyhai/AchillesLazy Loading• @Lazy, typiquement collections/maps• Champs chargés à l’appel du getter• Chargement complet des collections/maps parslice query• Champs de jointure toujours lazy, par choix deconception16
  • 17. https://github.com/doanduyhai/AchillesJointures• Besoin de cohérence forte au détriment de laperformance• Join collections/maps ->– Optimisation avec MultiGet Slice Query auchargement• 1 lecture pour n clés primaires dans la collection/map• 1 multiget slice query pour charger les n jointures (nlectures côté C*)– Batch mutation pour sauvegarder– Jointure possible sur les WideMap17
  • 18. https://github.com/doanduyhai/AchillesCascading• No cascade• PERSIST– écrase l’entité existante• MERGE– écrase les colonnes existantes si modifiées• REFRESH -> rien• REMOVE -> interdit/non supporté/mal• ALL -> tout sauf REMOVE18
  • 19. https://github.com/doanduyhai/AchillesWideMap API19@Entity@Table(name=«user»)class User@Idprivate Long userId;@Columnprivate String firstname;…..@Column(table=« tweet »)WideMap<UUID,String> tweets;10067e6162-3b6f-… 54947df8-0e9e-… 38400000-8cf0-…Hello world! #IppEvent avec #Achilles Ceci est un tweet...10firstname lastname ageJulien DUBOIS ???
  • 20. https://github.com/doanduyhai/AchillesWideMap API• insert(K key, V value, int ttl)• V get(K key)• remove(K key)• List<KeyValue<K, V>> find(K start, K end, int count)• List<KeyValue<K, V>> findBoundsExclusive(K start, K end,int count)• List<KeyValue<K, V>> findReverse(K start, K end, int count)• List<KeyValue<K,V>> findFirst(int count)• List<KeyValue<K,V>> findLast(int count)• KeyValueIterator<K,V> iterator(int count)• ...20
  • 21. https://github.com/doanduyhai/AchillesWideRow• Entité avec une primary Key + WideMap• Représente directement une column family21@Entity@WideRowpublic class TweetLine@Idprivate Long id;@Columnprivate WideMap<UUID, String> tweets;10uuid1 uuid2 uuid3 uuid4 uuid5Test Hellow World Démo Achilles CQL3 Ipp Event
  • 22. https://github.com/doanduyhai/AchillesCounter API• get()• incr(), incr(n)• decr(), decr(n)• Pas de suppression de compteur, c’est mal• WideMap<xxx,Counter> possible -> column familycounter dédiée22@Idprivate Long userId;@ColumnCounter tweetsCount;"User:10"tweetsCount friendsCount followersCount150 1000 420"Tweet:067e6162-3b6f"likesCount retweetCount5000 15000
  • 23. https://github.com/doanduyhai/AchillesUsage23user.getTweets().insert(uuid, «content »);List<KeyValue<UUID,String>> first10 = user.getTweets().findFirst(10);List<String> last10Tweets = user.getTweets().findLastValues(10);user.setTweets(xxx);• WideMapLong tweetCount = user.getTweetCount().get();user.getTweetCount().incr(3);user.setTweetCount(xxx);• Counter
  • 24. https://github.com/doanduyhai/AchillesDémoComment faire un clone de Twitteravec Achilles24
  • 25. https://github.com/doanduyhai/AchillesCompromis• La lecture des tweets doit être très très rapide• L’envoi des tweets doit être relativementrapide• La suppression des tweets peut être lente25
  • 26. https://github.com/doanduyhai/AchillesScénario 1• Modéliser un utilisateur• Modéliser la liste des amis/suiveurs• Implémenter un compteur d’amis/suiveurs• Implémenter la fonctionnalité « A suit B »• Donner la liste des amis/suiveurs d’unutilisateur• Donner les détails sur un utilisateur26
  • 27. https://github.com/doanduyhai/AchillesScénario 2• Modéliser un « Tweet »• Implémenter l’envoi de tweet• Dupliquer le tweet– dans la liste des tweets propres à l’utilisateur– dans la timeline de l’utilisateur– dans la timeline de tous ses suiveurs27
  • 28. https://github.com/doanduyhai/AchillesScénario 3• Supprimer un tweet– de la liste des tweets de l’utilisateur– de la timeline de l’utilisateur– de la timeline de tous ses suiveurs28
  • 29. https://github.com/doanduyhai/AchillesScénario 4• Implémenter la gestion des hashtags• Créer une tag-line pour les tags• Gérer l’effacement du tweet de la taglinelorsque le tweet est effacé29
  • 30. https://github.com/doanduyhai/AchillesScénario 5• Donner la possibilité de mettre un tweet en« favori » -> favoriteline• Détecter les personnes citées dans les tweets(@login) -> mentionline• Gérer l’effacement de la favoriteline et de lamentionline lorsque le tweet est effacé30
  • 31. https://github.com/doanduyhai/AchillesClés Composite• Interface marqueur MultiKey• Annotation dédiée @Key(order=x)31@JoinColumnprivate WideMap<UserIndex, User> user;public class UserIndex implements MultiKey{@Key(order=1)private String login;@Key(order=2)private Long id;}
  • 32. https://github.com/doanduyhai/AchillesConsistency Level• Par annotation32@Consistency(read=ONE,write=QUORUM)public class User@Column@Consistency(read=ONE,write=QUORUM)private Counter tweetsCount;@Column@Consistency(read=ONE,write=THREE)private WideMap<UUID,String> tweets;• Au runtime– persist(tweet,QUORUM)– merge(user,ALL)– tweetWideMap.insert(uuid1, «a tweet», ONE)
  • 33. https://github.com/doanduyhai/AchillesTTL33• Sur les opérations JPA– persist(entity, ttl)– persist(entity, ttl, writeCL)– merge(entity, ttl)– merge(entity, ttl, writeCL)• Sur les WideMap– user.getTweets().insert(uuid, «content», ttl)• Pas de TTL sur les counters (pas de tombstones)
  • 34. https://github.com/doanduyhai/AchillesLe futureQue nous réserve Achilles dansquelques mois ?34
  • 35. https://github.com/doanduyhai/AchillesProjection• Support complet de CQL3– @NamedQuery, query data mapper– Prepared statement (perf)– Batches « atomiques »– Row key composite (clustering)• Interceptors (@PrePersist,@PreRemove…)• Listeners• Bean Validation (JSR 303)• Secondary index• Callable, Future<>…35
  • 36. https://github.com/doanduyhai/AchillesRetour d’expérience CQL3• PreparedStatement (select fn,ln,age from User where userId=?)– Stocké côté serveur (100.000 max) et par Node– Seules les valeurs sont envoyées à l’exécution– Valeurs nulles possible -> effacer le champ– Pas possible de binder CL, TTL, Timestamp,possible dans C* 2.0– Pas de batch de PS, possible dans C* 2.0– Pas de IN (?) binding pour faire du MultiGet36
  • 37. https://github.com/doanduyhai/Achilles 37Retour d’expérience CQL3• List/Set/Map démystifié– Nouveaux serializers:• ColumnToCollectionType• ListType, SetType,MapType– List: index = timeUUID généré• insertion rapide avec append/prepend• ré-écriture + décalage si insertion par index• read-before-write pour enlever un élément quelconque– Set: valeur stockée directement dans ColumnName– Map: columnName contient la clé
  • 38. https://github.com/doanduyhai/AchillesRetour d’expérience CQL3CREATE TABLE users (user_id int PRIMARY KEY,emails set<text>,top_places list<text>,todo map<int, text>);INSERT INTO users(user_id,emails,top_places,todo)VALUES(1,{ddoan@test.com,dhdoan@gmail.com},[Paris,Chatillon’],{1:Demo Achilles, 2:Implement CQL3});RowKey: 1=> (column=, value=, timestamp=1362010585307000)=> (column=emails:64646f616e40746573742e636f6d,value=, timestamp=1362010585307000)=> (column=emails:6468646f616e40676d61696c2e636f6d,value=, timestamp=1362010585307000)=> (column=todo:00000001,value=44656d6f20416368696c6c6573, timestamp=1362010585307000)=> (column=todo:00000002,value=496d706c656d656e742043514c33,timestamp=1362010585307000)=> (column=top_places:16ae51c0813c11e289730dd4d81b4c6b,value=5061726973, timestamp=….)=> (column=top_places:16ae51c1813c11e289730dd4d81b4c6b,value=43686174696c6c6f6e, timestamp=…)38
  • 39. https://github.com/doanduyhai/AchillesAchilles est open-source donc …39We need you !!!github.com/doanduyhai/Achilles