Stratégie de stratégie primaire Android (application distribuée)

Je vais implémenter une application distribuée avec plusieurs clients mobiles et une application serveur basée sur le Web. Ainsi, chaque client et aussi le serveur sont autorisés à générer des entrées de table. Par conséquent, j'ai besoin de clés primaires uniques sur tous les participants et je souhaite pouvoir générer des clés hors ligne .

Quelle est la meilleure approche pour générer des clés primaires que vous utilisez sur les environnements distribués? Pour une question similaire, consultez Quelle est la meilleure stratégie clé principale pour une application mobile multi-client en ligne / hors ligne avec la base de données SQLite et Azure SQL en tant que magasin central?

  • Comment vérifier si mon application est autorisée à afficher une notification
  • Infinity ViewPager
  • Comment détecter si une notification a été rejetée?
  • Définir la couleur de forme Android de manière programmée
  • API Spotify: INVALID_APP_ID
  • Envoyer un MMS depuis mon application sur Android
  • Je suis conscient que la génération de clé UUID est une bonne approche pour ce scénario, mais je souhaite m'accrocher à une clé avec le nom _id et le type long comme suggéré par la plate-forme Android.

    Je ne souhaite pas avoir un identifiant composite avec l' identifiant id ( ID du serveur). Cette approche ne fonctionnerait pas bien, car le serveur devrait pouvoir générer des entrées pour un certain client. Dans ce cas, je devrais utiliser l'identifiant de l'appareil sur le serveur.

    Par conséquent, mon préféré actuel est de construire ma clé avec un type de données long (j'ai fait cela avant dans un autre projet). Je pense que je vais utiliser l'approche haute / basse (voir par exemple ici quel est l'algorithme Hi / Lo? ) Et avoir une clé qui se compose de:

    • Identifiant client (p. Ex. ~ 28 bits) généré à partir du serveur
    • Faible valeur (par exemple ~ 4 bits) augmentée sur le client, jamais persistée
    • Une valeur élevée (par exemple ~ 32 bits) augmentée sur le client, a persisté sur le client uniquement

    L'ID du client doit être extrait du serveur au premier démarrage de l'application mobile. Le premier démarrage nécessite donc une connexion réseau. Cela pourrait être un inconvénient de cette approche. Lors de l'identification du client sur l'appareil, je peux générer des clés sans connexion réseau.

    Normalement, l'id élevé est une valeur unique sur la base de données. Lorsqu'un utilisateur désinstalle l'application et l'installe à nouveau, je dois le traiter comme un nouveau client et lui donner un nouvel identifiant client. Sinon, je devrais enregistrer l'identifiant élevé actuel sur le serveur pour pouvoir le restaurer lors de la perte ou lors de la réinstallation – ne vaut pas l'effort.

    Quelle est la meilleure approche pour obtenir le haut identifiant sur Android? Une clé d'autoincrement n'est pas une solution. J'ai besoin de quelque chose comme une fonction de générateur. Et il doit être exécuté dans sa propre transaction (pas la transaction "utilisateur"). Quelqu'un at-il expérimenté avec cette approche sur Android et quelqu'un peut-il me pointer dans la bonne direction? (Je n'ai trouvé que cette réponse ).

    Quelle stratégie clé utilisez-vous pour votre application multi-client (en ligne et hors ligne)?

  • SMS Broadcastreceiver n'est pas appelé lorsque GO SMS Pro est installé
  • AsyncTaskLoader onLoadFinished avec une tâche en attente et un changement de configuration
  • ClassNotFoundException pour SignInConfiguration lors de la connexion avec Google
  • ViewPager wrap_content ne fonctionne pas
  • Java.util.ConcurrentModificationException dans les tests JUnit
  • Afficher le clavier doux pour la boîte de dialogue
  • 5 Solutions collect form web for “Stratégie de stratégie primaire Android (application distribuée)”

    Il s'agit de plus de questions puis de réponses …

    Cela rend les choses plus faciles si vous pouvez générer automatiquement tous vos identifiants, donc vous ne devez pas les chercher sur le serveur et vous inquiétez si vous avez une connexion. Vous mentionnez que vous ne pouvez pas adopter l'approche commune (UUID ou ANDROID_ID) car vous utiliserez un long "comme l'a suggéré la plate-forme Android".

    Êtes-vous en train de faire référence au fait qu'Apple suppose que vos tables SQLite auront une longue clé principale _id?

    Utilisez-vous un magasin de données ou une base de données SQL sur votre serveur?

    Si vous utilisez un magasin de données avec des clés hiérarchiques (par exemple, le magasin de données Google), qu'en est-il si vous utilisez UUID / ANDROID_ID comme identifiant client, puis un identifiant de l'élément de données long. Ensuite, sur le client, vous stockez le long, et sur le serveur, vos entités sont stockées avec un chemin d'accès de clé de UUID / long.

    Pourquoi écrivez-vous que «l'identifiant élevé doit être une valeur unique sur la base de données»? Puisqu'il est précisé avec l'identifiant du client, peut-être que vous voulez dire qu'il doit être unique sur la base de données locale?

    Pour gérer votre problème que l'utilisateur pourrait désinstaller et réinstaller l'application, pourquoi ne pas poursuivre votre idée de "sauvegarder l'identifiant élevé actuel sur le serveur pour pouvoir le restaurer lors de la perte ou lors de la réinstallation". Comme vous avez déjà l'intention de récupérer l'identifiant du client lors de la première exécution (et ne peut pas attribuer d'identifiants jusqu'à ce que vous l'ayez), vous pouvez également demander au serveur le prochain identifiant haut disponible.

    Vos entités disposent-elles d'un autre élément clé de sorte que vous puissiez générer un hash de 32 bits à partir de ce matériel pour votre ID élevé? En supposant que l'identifiant élevé doit être unique sur un client particulier (et en supposant que vous n'aurez pas un nombre massif d'entités sur un client), je pense que vous ne rencontrerez jamais une collision si vous avez un matériel clé décent et utilisez un hash Fonction qui minimise les collisions.

    Permettez-moi de voir si je comprends bien: vous avez besoin d'un numéro de 32 bits unique à l'appareil? D'accord:

    1. Créez le numéro de manière aléatoire ou en hachant le nanotime actuel. Cela vous donnera une chaîne assez unique.
    2. Ensuite, demandez au serveur si ce numéro a déjà été utilisé. Si c'est le cas, générez le numéro à nouveau et demandez à nouveau.

    Si vous hachiez le nanotime, il est tellement impossible (pas totalement impossible, la résistance à la collision n'est pas collision) pour obtenir le même nombre. Étant donné le reste de votre chaîne, cela rendrait totalement unique. Cette méthode n'exige pas d'interactions avec le serveur jusqu'à ce qu'il soit nécessaire d'utiliser le serveur. Dites que le client n'est pas connecté au premier démarrage: générez le numéro, enregistrez-le et quand il se connecte, avant que rien ne se produise, vérifiez si le périphérique existe. Si c'est le cas, commencez par zéro. De cette façon, vous pouvez obtenir un identifiant d'appareil vraiment unique.

    Il n'y a aucun moyen de savoir avec certitude que les clés générées sur le client sont uniques sur le serveur DB jusqu'à ce que vous communiquez avec le serveur.

    Si vous communiquez devant le serveur avant de créer des enregistrements du côté client, vous pouvez réserver une gamme de clés sur le serveur. Par exemple, le serveur pouvait distribuer des clés en lots de 10 000. Le client communique avec le serveur et réserve le début du prochain lot de clés disponibles, disons 60 000. Le client est alors libre de créer des enregistrements avec des identifiants de 60 000 à 69 999. Une fois que le client manque de clés, il doit demander une nouvelle gamme de clés. Si tous les clients et les clés de réserve du serveur pour eux-mêmes comme ceci, tous les ID générés seront uniques dans la base de données du serveur.

    Maintenant, si vous créez des enregistrements du côté client avant de communiquer avec le serveur, vous devriez être obligé de corriger ces identifiants une fois que vous obtenez une plage réservée du serveur afin qu'ils soient dans cette plage, avant de synchroniser ces enregistrements avec le serveur .

    Je ne sais pas pourquoi vous essayez d'inclure un identifiant client dans la clé; Le serveur attribue la valeur élevée, et cela suffit pour obtenir des clés uniques générées sur le client.

    De mon expérience: utilisez des identifiants locaux sur le périphérique et identifiez-les séparément sur le serveur . Chaque fois que vous communiquez des données sur le fil, convertissez-vous de l'un à l'autre. Cela permettra de clarifier le processus et de faciliter le débogage. Les routines de conversion restent petites, sont bien isolées et représentent un élément naturel dans l'architecture de l'application. Les données se déplaçant sur le fil devraient être relativement petites, de toute façon, et la conversion d'ID ne sera pas une grosse surcharge. En outre, la quantité de données conservées sur l'appareil mobile est, vraisemblablement, faible (la masse est sur le serveur).

    Je propose de faire une conversion sur l'appareil avec une table simple local_ID <-> server_ID . Le serveur ne doit fournir qu'une seule procédure: générer un lot de clés, disons 444 nouvelles clés, ce qui, vraisemblablement, le périphérique mobile attribuera ensuite à ses identifiants locaux et envoie des données au serveur avec les ID serveur uniquement. Le tableau de conversion peut être occasionnellement purgé des identifiants inutilisés, et les identifiants locaux peuvent être réutilisés, les nombres entiers 32 bits suffiront certainement.

    Motivation

    Les tables restent petites, la mise en œuvre reste optimale pour l'architecture des périphériques natifs, isolée des changements architecturaux imprévisibles ailleurs et il existe un bon point de débogage et de traçage, à travers lequel passent toutes les données.

    J'ai eu une application régénérer tous les identifiants sur chaque sauvegarde et chargement de fichiers de données. Il était inopinément simple, rapide et ouvert d'autres possibilités élégantes comme la défragmentation et la consolidation de l'espace d'identification.

    Dans votre cas, vous pouvez modifier la technologie du serveur avec des modifications minimales à l'application cliente. Étant donné que le client peut fonctionner hors ligne de toute façon, il ne peut utiliser que les identifiants locaux dans la plupart des fonctions. Seul le module de synchronisation récupère et convertit les identifiants de serveur.

    J'ai offert deux primes sur cette question et je n'ai pas trouvé la réponse que je cherchais. Mais j'ai passé du temps à penser à la meilleure solution et peut-être que la question n'était pas suffisamment ouverte et axée sur la solution que j'avais à l'esprit.

    Cependant, il existe de nombreuses stratégies différentes, maintenant (après la deuxième prime), je pense que la première question à répondre est quel (s) modèle (s) de données avez-vous dans votre environnement distribué? Vous pourriez avoir

    1. Le même modèle de données (ou un sous-ensemble) sur le client et le serveur
    2. Modèle de données client différent et modèle de données du serveur

    Si vous répondez avec 1), vous pouvez choisir votre stratégie clé à partir de

    • Utilisant GUID
    • En utilisant mon approche High / Low
    • Les clés de mappage comme @ user3603546 ont suggéré

    Si vous répondez avec 2), seuls les éléments suivants viennent à l'esprit

    • Identifiant composite

    Je n'ai jamais aimé les ID composites, mais quand je pense à cela (et je ne l'appelle pas ID composite de toute façon), il pourrait être une solution possible. Ensuite, je souhaite esquisser cette solution:

    Glossaire:

    • <Clé client> … clé primaire générée du côté client, de sorte que le client choisit la mise en œuvre (long _id pour Android)
    • <Clé du serveur> … clé primaire générée du côté du serveur, de sorte que le serveur choisit la mise en œuvre
    • <Identification du client> … ID pour identifier le client
    • <Id de périphérique> … ID pour identifier le périphérique, il existe une relation 1-n entre le client et le périphérique

    Solution:

    • Utilisez-le uniquement si vous disposez d'un modèle de données client et d'un modèle de données de serveur
    • Le modèle de données client a les champs
      • <Clé client> clé primaire
      • <Clé du serveur> champ de données annulables
    • Le modèle de données du serveur comporte les champs
      • <Clé du serveur> comme clé primaire
      • <Clé client> champ de données nullable
      • <Id client> comme champ de données obligatoire pour distinguer le client
    • Lors de la synchronisation entre un serveur et un client, générez une <clé client> manquante sur le client et marquez l'entrée comme sale (de sorte que l'identifiant client arrive au serveur en fin de journée)
    • Lors de la synchronisation du client au serveur, générez la <clé du serveur> manquante sur le serveur avant de la sauvegarder
    • Le mappage entre le modèle de données client et serveur peut être géré par des frameworks spécialisés comme Dozer ou Orika , mais la génération de clé doit être intégrée lors de la réalisation du mappage.

    Je n'ai jamais aimé cette solution parce que j'ai toujours pensé en termes de modèle de données de serveur. J'ai des entités qui ne vivent que sur le serveur et j'ai toujours voulu créer ces entités sur le client qui ne seraient pas possibles. Mais quand je pense que dans le modèle de données client, je pourrais avoir une entité par exemple. Produit qui aboutit à deux entités (Product and a ClientProduct) sur le serveur.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.