https://github.com/doanduyhai/Achilles 14
Persistance avec Thrift
• Persistance des Sets
10
1265231 68754 546546
#Cassandra #Achilles #Tatami
• Persistance des Maps
10
113131 6543213 51313 65465464
{language:Java} {database:Cassandra} … …
https://github.com/doanduyhai/Achilles
Dirty check
• Interception seulement sur getter (internal calls )
• Pas d’update atomique des collections/maps
• Dirty check des collections/maps coûteux en Thrift
Impl
– (read + delete) + write pour mettre à jour (pas de slice
delete)
– optimisation possible pour Set & Map
– list.add(2,peter) ???
– faible cardinalité conseillée (10 -20)
15
friends
0 1 2 3 4
bob alice john helen richard
https://github.com/doanduyhai/Achilles
Lazy Loading
• @Lazy, typiquement collections/maps
• Champs chargés à l’appel du getter
• Chargement complet des collections/maps par
slice query
• Champs de jointure toujours lazy, par choix de
conception
16
https://github.com/doanduyhai/Achilles
Jointures
• Besoin de cohérence forte au détriment de la
performance
• Join collections/maps ->
– Optimisation avec MultiGet Slice Query au
chargement
• 1 lecture pour n clés primaires dans la collection/map
• 1 multiget slice query pour charger les n jointures (n
lectures côté C*)
– Batch mutation pour sauvegarder
– Jointure possible sur les WideMap
17
https://github.com/doanduyhai/Achilles
WideMap 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
https://github.com/doanduyhai/Achilles
WideRow
• Entité avec une primary Key + WideMap
• Représente directement une column family
21
@Entity
@WideRow
public class TweetLine
@Id
private Long id;
@Column
private WideMap<UUID, String> tweets;
10
uuid1 uuid2 uuid3 uuid4 uuid5
Test Hellow World Démo Achilles CQL3 Ipp Event
https://github.com/doanduyhai/Achilles
Counter API
• get()
• incr(), incr(n)
• decr(), decr(n)
• Pas de suppression de compteur, c’est mal
• WideMap<xxx,Counter> possible -> column family
counter dédiée
22
@Id
private Long userId;
@Column
Counter tweetsCount;
"User:10"
tweetsCount friendsCount followersCount
150 1000 420
"Tweet:067e6162-3b6f"
likesCount retweetCount
5000 15000
https://github.com/doanduyhai/Achilles
Scé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’un
utilisateur
• Donner les détails sur un utilisateur
26
https://github.com/doanduyhai/Achilles
Scé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 suiveurs
27
https://github.com/doanduyhai/Achilles
Scé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 la
mentionline lorsque le tweet est effacé
30
https://github.com/doanduyhai/Achilles
Consistency Level
• Par annotation
32
@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)
https://github.com/doanduyhai/Achilles
TTL
33
• 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)
https://github.com/doanduyhai/Achilles
Projection
• 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
https://github.com/doanduyhai/Achilles
Retour 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 MultiGet
36
https://github.com/doanduyhai/Achilles 37
Retour 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é