J'ai un service Web de repos qui prend fondamentalement longtemps comme nombre et indique si le nombre est premier ou non, c'est-à-dire en clair / texte vrai ou faux.
des millions d'utilisateurs utilisent ce service.
Maintenant, un utilisateur envoie un très grand nombre comme (15-20 chiffres / grand nombre) et mon service prend du temps pour calculer si le nombre est premier ou non. Cet utilisateur envoie des milliers de demandes en continu pour le même nombre. Alors, comment gérer ces mêmes milliers de demandes.
Par exemple:
Envoi du numéro 101221323232324343 dans la requête et mon service prend, disons 3 secondes, pour savoir si le nombre est premier ou non. Maintenant, il envoie 1 000 requêtes par seconde.
comment gérer ce cas?
3 Réponses :
Vous pouvez stocker des valeurs supérieures à un nombre donné de chiffres dans une base de données. Chaque fois qu'un tel numéro est reçu, vous pouvez stocker s'il est premier dans la base de données. Vous pouvez également utiliser un cache pour stocker les n dernières valeurs différentes, donc, lorsqu'un nombre est demandé, vous vérifiez s'il est trop long. Sinon, calculez simplement. S'il est trop long, recherchez-le dans le cache. Si c'est là, retournez-le. Si ce n'est pas là, recherchez-le dans la base de données. Si c'est le cas, ajoutez-le au cache (et supprimez éventuellement la valeur la plus ancienne) et renvoyez-le à l'utilisateur. Si ce n'est même pas dans la base de données, calculez-le, stockez-le dans la base de données, ajoutez-le au cache et renvoyez la réponse à l'utilisateur.
@VJS vous êtes les bienvenus. Vous pourriez envisager de l'accepter comme la bonne réponse si elle a résolu votre problème. Quoi qu'il en soit, je vous souhaite bonne chance pour résoudre ce problème intéressant.
C'est une excellente réponse. C'est une approche simple. En pensant simplement, pouvons-nous faire autre chose pour gérer ce scénario. Je veux dire, y a-t-il une meilleure solution ...
@VJS vous pouvez utiliser des techniques d'optimisation supplémentaires. Par exemple, si la somme des chiffres est divisible par 3, alors le grand nombre n'est pas un nombre premier. Si le dernier chiffre est une paire, alors le grand nombre n'est pas premier. Si vous avez un autre nonprime, qui est assez proche de ce nombre, vous pouvez vérifier la différence. Par exemple, si l'autre nombre non premier était divisible par sept et que la différence est divisible par sept, alors vous avez un non-prime.
Je vérifierais le coût d'E / S (étant donné la recherche hautement simultanée) par rapport au temps de calcul avant d'aller pour n'importe quelle base de données. De plus, sans stratégie d'éviction raisonnable, la base de données occupera rapidement tout le stockage car le problème est illimité :)
@NotThreadSafe
public CheckIfPrime extends Servelet {
private Long lastNumber;
private Long isLastNumberPrime;
public Long operation(ServeletRequest req, ServeletResponse res) {
if(getNumberFromRequest(req) == lastNumber) {
return isLastNumberPrime;
} else {
return checkForPrimeNumber(getNumberFromRequest);
}
}
}
Use synchronisation primitives to honour the class' invariants and postconditions (one way can be to use AtomicLong instead of Long)If you think the number of requests can be too huge (exhausting memory), consider using a distributed cache.For very high TPS, make your application reactive. The checkForPrime()opeeation can be done asynchronously. Why block the calling thread?
La probabilité d'atteindre la même valeur que la dernière étant donné le nombre de requêtes est proche de zéro, donc cette optimisation est inutile.
Oh, pourquoi pensez-vous que ce sera presque zéro? Comme le PO l'a mentionné, il peut y avoir des milliers de demandes contenant le même nombre.
La même chose n'est pas la dernière: comme OP l'a dit "des millions d'utilisateurs utilisent le service" et il y aura sûrement des milliers de répétitions de milliers de nombres égaux, donc effectivement ce sera un nouveau nombre à chaque fois par rapport au dernier. De plus, votre exemple n'est pas thread-safe: vous devez utiliser une référence atomique pour la paire valeur / indicateur et la permuter en conséquence.
Dans ce cas, pouvons-nous utiliser un ConcurrentHashMap contenant le nombre et son résultat booléen?
Voir ma réponse (séparée), étant donné que le problème est illimité, votre code manquera rapidement de mémoire sur une carte standard, simultanée ou non.
Oh, donc vous utilisez un cache avec expiration. Logique.
Vous pouvez utiliser un cache en mémoire expulsant en ajustant ses paramètres par rapport à la taille maximale de la mémoire ou TTL. Pour des informations générales, vérifiez par ex. Expulsion du cache LFU . Il existe de nombreuses implémentations alors que je recommanderais la bibliothèque de caféine de Ben Manes pour son efficacité. Vous pouvez utiliser une base de données, mais dans ce cas, les E / S peuvent être plus chères qu'un nouveau calcul, donc je limiterais probablement la mise en cache à la mémoire uniquement.
Je suppose que vous pouvez utiliser un cache en mémoire.
Il y a tellement d'utilisateurs avec des nombres différents aussi ... le cache va être trop gros ... ne pensez pas que le cache est une bonne solution ...
Vous pouvez donc faire de la magie ...: bexause Soit vous utilisez de la mémoire pour gagner du temps de traitement, soit vous économisez plus de temps de traitement à chaque requête .... Il n'y a pas de troisième option, si vous avez une approche de cache intelligent, vous pouvez économiser de la mémoire, pas simple mettre chaque requête dans le cache
Pour éviter que les utilisateurs n'envoient beaucoup de demandes, vous devez les limiter.