2017-05-15 6 views
0

J'ai une table, Foo. J'ajoute des lignes à cette table sur certains événements. La conception globale actuelle est telle que les messages en double ne peuvent pas être évités. Cela entraîne l'ajout de lignes en double dans la table.Éviter les lignes dupliquées via redisson

Je ne peux pas mettre une contrainte unique sur la table car il existe différents types de messages qui deviennent des lignes dans cette table. Je souhaite éviter les doublons uniquement pour un type de message spécifique.

Étant donné que les messages en double viennent souvent en même temps, et que cette application s'exécute sur plusieurs nœuds, j'ai décidé d'utiliser radisson pour prendre un verrou distribué. Cependant, cela ne semble pas fonctionner. Je reçois toujours des lignes en double dans la table.

Des messages en double sont détectés en fonction de userId, de la date et du type. Voici le code démo minimaliste. J'essaie de faire une lecture avant l'écriture et cette lecture se passe dans un bloc synchronisé entre les nœuds d'application.

Appréciez toutes les entrées à ce sujet.

 if(updateEntry.getType().equals(Type.XYZ) { 
     java.sql.Date date = updateEntry.getDate(); 
     String redisLockKey = "MyAPP" + "-" + userId+"-"+date.toString()+ "-" + "type-XYZ"; 
     RLock rLock = redissonClient.getLock(redisLockKey); 
     rLock.lock(5, TimeUnit.SECONDS); 
     MyEntity myEntity = myEntityRepository.findByUserIdAndDateAndActivityType(userId,date,Type.XYZ); 
     if(null == myEntity) { 
      myEntity = new MyEntity(); 
      // myEntity setters 
     myEntity = myEntityRepository.saveAndFlush(myEntity); 
     } 
     rLock.unlock(); 
    } 

Répondre

0

J'ai trouvé le problème. Le bloc de code ci-dessus était dans @Transactional. Avec le niveau d'isolement par défaut du ressort, c'était REPEATABLE_READ à mysql. Prendre le verrou en dehors de la transaction a réglé le problème.

0
MyEntity myEntity = myEntityRepository.findByUserIdAndDateAndActivityType(userId,date,Type.XYZ); 
if(null == myEntity) { 
    myEntity = new MyEntity(); 
    // myEntity setters 
    myEntity = myEntityRepository.saveAndFlush(myEntity); 
} 

Selon cette partie du code, vous traitez userId, la date et tapez critères uniques pour décider si vous pouvez insérer ce disque. Alors pouvez-vous expliquer pourquoi vous ne pouvez pas les faire ensemble en tant que contraintes uniques combinées.