W mojej aplikacji (Spring) użytkownicy mogą dostać się do obiektów (nie chodzi o obiekty Javowe, a o aplikacje, którymi użytkownicy zarządzają) za pomocą UUID. Jest pewna operacja, która nie powinna zostać jednocześnie wiele razy uruchamiana dla danego UUID.
Mam takie proste rozwiązanie
@Service
class Facade {
private static final Set<String> locks = Collections.newSetFromMap(new ConcurrentHashMap<>());
Either<Error, Result> foo(String uuid) {
if (locks.contains(uuid)) {
return "Error: operation in progress";
}
locks.add(uuid);
try {
return bar(uuid); //rozne operacje, miedzy innymi na bazie
} finally {
locks.remove(uuid);
}
}
}
To będzie działać, jeżeli wystawię użytkownikom tylko jedną instancję mojej aplikacji (tytułowy serwis). Co, gdybym chciał to przeskalować? Co, gdyby skala była poważna?
- W moim przypadku operacja
bar(uuid)
jest wykonywana rzadko, a jej wielokrotne uruchomienie w tym samym czasie to efekt przypadku lub złośliwości użytkownika. Myślę, żeby po prostu dodać kolumnę w bazie, w której będzie przechowywany lock. - I do sedna tego wątku. Co w odwrotnej sytuacji - częste próby wykonania jakiejś operacji (niewynikające z przypadków i złośliwości użytkowników), wielu użytkowników, wiele instancji serwisu na różnych maszynach? Słyszałem kiedyś o Redis - nie używałem. Czy to byłoby dobre rozwiązanie? Jak się rozwiązuje takie problemy?