Question

Y at-il un générateur de numéro séquentiel système géré niveau? DateTime.Now.Ticks ne le fera pas parce que les opérations que je fais parfois se produisent plus d'une fois par tick.


Exigence Clarifications:

  • Processus agnostique -. Il n'y a vraiment qu'un seul processus qui accéderont à ce
  • La performance est essentielle! Il est utilisé pour consigner les impressions sur un AdServer, qui peut atteindre 1k / s

Il devrait être l'un des éléments suivants:

  • Un numéro de séquence de 4 octets qui remet à zéro tous les tiques
  • Un numéro de séquence de 12 octets - essentiellement en ajoutant 4 octets de granularité pour un C
Était-ce utile?

La solution

Aucun de ceux qui sont destinés à cela, mais vous pouvez utiliser System.Diagnostics.PerformanceCounter . Vous pouvez également utiliser le Registre, mais vous auriez besoin de sérialisation accès en lecture / écriture accross les processus.

System.Diagnostics.PerformanceCounter pc 
    = new System.Diagnostics.PerformanceCounter("SeqCounter", "SeqInstance");
long myVal=pc.Increment();

Modifier

Plus je pense à cela, je pense que cela pourrait être une belle solution. Incrémenter augmentera le compteur de 1 à une opération atomique qui devrait fonctionner accross tous les processus sur un système.

Modifier

Sur la base de vos modifications, je recommande de ne pas utiliser un compteur de performance. Un compteur de performance était un moyen de multiples processus cordinate accross. Je ne sais pas comment le implemention interne est codée.

Pourquoi ne pas simplement utiliser une variable statique et incrémenter? Votre devoir verrouiller quelque chose si vous voulez que ce soit threadsafe.

System.Threading.Interlocked.Increment

Pour votre information. Si vous utilisez la version longue sur un système 32 bits, il ne sera pas nessecarilly être thread-safe


Modification de montrer la implemention je (DS):

public static class Int32Sequencer
{
    private static Int32 lastSequence = Int32.MinValue;
    private static Object lockObject = new Object();
    public static Int32 GetNextSequence()
    {
        lock (lockObject)
        {
            unchecked { lastSequence++; }
            return lastSequence;
        }
    }
}

Autres conseils

A Guid est aussi proche que vous allez obtenir, mais ce sont « unique » et pas nécessairement séquentielle. Si vous voulez vraiment séquentielle sur plusieurs processus au niveau du système, vous devrez probablement rouler votre propre.

EDIT:

Ok, donc de vos nouvelles exigences, je vais supposer:

  1. Un seul processus doit faire le travail
  2. Vous apposent à une base de données

Voici donc ce que je recommande:

  1. Au processus de démarrage, interroger la base de données pour la dernière valeur (plus) (0 si aucune existe).
  2. Utilisez simple de long et incrément pour chaque ligne DB. Vous allez vouloir insérer dans les lots en raison de votre débit de données élevé.

Cela devrait le faire. Rester simple. Cela n'a pas de serrures, une légère (négligeable) a frappé au démarrage, et des numéros séquentiels dans votre base de données. Cet algorithme est également processus agnotic aussi longtemps que vous avez un processus exécutant.

Je pense que la chose la plus proche est un guid, qui, comme je suis sûr que vous êtes au courant est au mieux que partiellement séquentiel.

Il y a un article ici qui donne des détails pour le serveur SQL: GUID séquentiel de dans SQL serveur Cette technique est utilisée pour minimiser les fractionnements en raison du caractère aléatoire du GUID. Peut-être que ce lien vous donnera quelques conseils ou des idées.

Je pense que nous devons savoir un peu plus sur ce que vous recherchez. Pouvez-vous préciser votre question un peu. En particulier, le service ne fait ...

  • Vous avez besoin de travailler dans tous les processus, un processus ou un utilisateur particulier?
  • doit être unique numéros ou juste séquentiel?

En fonction de votre question, il semble y avoir deux ou trois différents éléments que vous pouvez rechercher.

Besoin d'un groupe séquentiel de nombres à travers tous les processus du système

AFAIK, No such existe un service. On devrait être assez facile à écrire, mais le faire fonctionner dans tous les processus est délicat.

Besoin d'un groupe séquentiel unique de chiffres dans tous les processus du système

Légère variation sur la première question. Un tel service n'existe pas parce qu'il serait impossible de mettre en œuvre. Il n'y a aucun moyen de garantir un numéro séquentiel unique en utilisant les types de données simplement intégrés car la valeur finira par déborder et vous laisser avec un numéro en double.

Besoin d'une méthode pour obtenir des valeurs uniques dans le système

Comme plusieurs autres utilisateurs ont mentionné le meilleur choix est une instance System.Guid. Vous pouvez en créer un nouveau en utilisant Guid.NewGuid (). Pour presque toutes les fins, ils peuvent être considérés comme uniques, mais ne sont pas séquentiels.

J'aime l'option de base de données simplement pour la sécurité. Assurez-vous d'installer un monstre serveur SQL avec de la bande passante entre allot vos serveurs avec une mémoire suffisante cependant. Un système similaire à celui mis en œuvre a été à la première entreprise que j'ai jamais travaillé (Avant même que je suis devenu un programmeur) et il était très douteux. Vous pouvez combattre à l'échelle cela.

Une autre option serait d'implémenter une fonction singleton dans votre code ... à condition qu'un seul domaine d'application sera l'appeler. Peut être un peu plus rapide que de faire un voyage de base de données. Si toutefois vous allez vous connecter ce genre de choses à la base de données de toute façon .... Qu'en est-il combiner les deux ... Exécuter un singleton pour la vitesse et puis écrire à la base de données lorsque les ressources le permettent.

Encore une fois, si l'exigence séquentielle est pas forte, un Guid serait votre meilleur pari.

Il n'y a pas moyen d'obtenir une seule série séquentielle sans verrouillage. Peu importe quel mécanisme que vous utilisez pour attribuer la valeur suivante - un compteur de performance, une variable statique, quel que soit -. Lorsque deux threads deux ont besoin de la valeur suivante en même temps, il faut attendre l'autre

La première chose que je ferais est d'écrire un programme de test qui a donné naissance à un grand nombre de fils que chaque fonction appelé à plusieurs reprises d'incrément de verrouillage tel que celui Daniel Schaffer affiché. Cela vous permettra de trouver le seuil où votre application commence à thrash -. Où il est passé plus de temps d'attente sur Monitor.Enter que de faire quoi que ce soit d'autre

Si cela se révèle être un problème - et je serais prêt à parier que si les volumes dont vous parlez sont réels, il - alors vous devriez faire chaque thread maintenir son propre compteur séquentiel, que vous pouvez faire en marquant le champ de compteur avec le ThreadStaticAttribute. Vous pouvez ensuite générer des identifiants uniques au large d'une combinaison de l'identifiant et le compteur du fil.

Cette approche ne fonctionnera pas si vous n'êtes pas en utilisant un pool de threads (depuis le compteur meurt lorsque le fil il appartient à fait). Et vous voulez probablement aussi de faire le compte de démarrage de l'application de la partie de l'ID de composé, de sorte que vous n'avez pas à écrire les compteurs de fil vers un stockage durable. (Si vous ne le faites pas, lors du redémarrage du serveur les fils commenceraient à générer des compteurs à zéro à nouveau, et si votre application a créé un fil avec le même ID que l'instance précédente, vous obtiendrez des identifiants en double.)

Ceci est évidemment pas trivial d'écrire (ou, plus important encore, test), donc je vous recommande vivement de prouver qu'il faut d'abord.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top