Android (verteilte Anwendung) Primärschlüsselstrategie

Ich werde eine verteilte Anwendung mit mehreren mobilen Clients und einer webbasierten Serveranwendung implementieren. So kann jeder Client und auch der Server Tabelleneinträge generieren. Deshalb brauche ich eindeutige primäre Schlüssel über alle Teilnehmer und ich möchte in der Lage sein, Schlüssel offline zu generieren .

Was ist der beste Ansatz für die Erstellung von Primärschlüsseln, die Sie in verteilten Umgebungen verwenden? Für eine ähnliche Frage siehe Was ist die beste primäre Schlüsselstrategie für eine Online / Offline-Multi-Client-Mobile-Anwendung mit SQLite und Azure SQL-Datenbank als zentraler Speicher?

Ich bin mir bewusst, dass UUID Key Generation ist ein guter Ansatz für dieses Szenario, aber ich möchte an einem Schlüssel mit Namen _id und Typ lange wie von der Android-Plattform vorgeschlagen.

Ich möchte keine Composite-ID mit Gerät haben (auch Server ist ein Gerät) id und lokale ID. Dieser Ansatz würde sowieso nicht gut funktionieren, da der Server in der Lage sein sollte, Einträge für einen bestimmten Client zu generieren. In diesem Fall müsste ich die Geräte-ID auch auf dem Server verwenden.

Deshalb ist mein aktueller Favorit, meinen Schlüssel mit Datentyp lange zu bauen (ich habe das schon in einem anderen Projekt gemacht). Ich denke, ich werde den High / Low- Ansatz nutzen (siehe zB hier Was ist der Hi / Lo-Algorithmus? ) Und einen Schlüssel, der aus:

  • Client-ID (zB ~ 28 Bits) aus dem Server generiert
  • Niedriger Wert (zB ~ 4 Bits) auf Client erhöht, nie bestanden
  • Hoher Wert (zB ~ 32 Bits) auf Client erhöht, nur auf Client bestanden

Die Client-ID muss beim ersten Start der mobilen Anwendung vom Server abgerufen werden. So braucht der erste Start eine Netzwerkverbindung. Dies könnte ein Nachteil dieses Ansatzes sein. Wenn ich die Client-ID auf dem Gerät habe, kann ich Schlüssel ohne Netzwerkverbindung generieren.

Normalerweise ist die hohe ID ein eindeutiger Wert über die Datenbank. Wenn ein Benutzer die Applikation deinstalliert und es wieder installiert, muss ich ihn als neuen Client behandeln und ihm eine neue Client-ID geben. Ansonsten müsste ich die aktuelle hohe ID auf dem Server speichern, um sie auf Verlust oder Neuinstallation wiederherstellen zu können – nicht die Mühe wert.

Was ist der beste Ansatz für das Erhalten der hohen ID auf Android? Ein Autoincrement-Schlüssel ist keine Lösung. Ich brauche etwas wie eine Generatorfunktion. Und es muss in seiner eigenen Transaktion ausgeführt werden (nicht die "User" Transaktion). Hat jemand Erfahrungen mit diesem Ansatz auf Android und kann jemand mich in die richtige Richtung zeigen? (Ich habe diese Antwort nur gefunden).

Welche Schlüsselstrategie verwenden Sie für Ihre Multi-Client-Anwendung (online und offline)?

  • SQLite Drop und Recreate Table
  • Java - java.lang.IllegalStateException: Die Zeile 0, col -1 konnte nicht aus CursorWindow gelesen werden
  • SQLiteAssetHelper NullPointerException nur auf einigen Geräten
  • Wie formatiere ich die WHERE-Klausel und '?' In einer SQLite-Abfrage?
  • Wie sorgfältig sollte ich mit Thread-Sicherheit bei der Erstellung von Methoden / Aktivitäten, die mit SQLite-Datenbank interagieren?
  • Durchsuchen von Daten in Android SQLite Datenbank
  • So deaktivieren Sie die Schaltfläche "Daten löschen" in der Anwendungsinformationen der Anwendung "Anwendung verwalten"
  • So verwenden Sie vorinstallierte SQLite-Datenbank in Android aus Assets
  • 5 Solutions collect form web for “Android (verteilte Anwendung) Primärschlüsselstrategie”

    Dies ist mehr Fragen dann Antworten …

    Es macht die Dinge einfacher, wenn man automatisch alle Ihre ID's generieren kann, also musst du sie nicht vom Server holen und dir Sorgen machen, ob du eine Verbindung hast. Sie erwähnen, dass Sie nicht den gemeinsamen Ansatz (UUID oder ANDROID_ID) nehmen können, weil Sie eine lange "wie von der Android-Plattform vorgeschlagen" verwenden werden.

    Verweisen Sie auf die Tatsache, dass Android davon ausgeht, dass Ihre SQLite-Tabellen einen langen _id Primärschlüssel haben werden?

    Verwenden Sie einen Datenspeicher oder eine SQL-Datenbank auf Ihrem Server?

    Wenn Sie einen Datenspeicher mit hierarchischen Schlüsseln verwenden (zB google datastore), dann wie über wenn Sie UUID / ANDROID_ID als Client-ID verwenden und dann eine lange als Datenelement-ID. Dann auf dem Client nur speichern Sie die lange, und auf dem Server Ihre Entitäten sind mit einem Schlüssel Pfad von UUID / long gespeichert.

    Warum schreibst du, dass die "hohe ID ein eindeutiger Wert über die Datenbank sein muss"? Da es mit der Client-ID vorangestellt ist, vielleicht meinst du, dass es in der lokalen Datenbank eindeutig sein muss?

    Um Ihr Problem zu lösen, dass der Benutzer die App deinstallieren und neu installieren könnte, warum nicht deine Idee von "speichern Sie die aktuelle hohe ID auf dem Server in der Lage sein, um es auf Verlust oder bei der Neuinstallation wiederherstellen". Da Sie bereits planen, die Client-ID beim ersten Lauf abzurufen (und keine IDs zuweisen können, bis Sie es haben), können Sie auch den Server für die nächste verfügbare High-ID fragen.

    Haben Ihre Entitäten ein anderes wichtiges Material, so dass Sie einen 32-Bit-Hash aus diesem Material für Ihre hohe ID generieren könnte? Angenommen, dass die hohe ID nur auf einem bestimmten Client eindeutig sein muss (und vorausgesetzt, Sie werden nicht eine massive Anzahl von Entitäten auf einem Client haben), dann denke ich, dass Sie nie eine Kollision bekommen würden, wenn Sie anständiges Schlüsselmaterial haben und einen Hash verwenden Funktion, die Kollisionen minimiert.

    Lass mich sehen, ob ich das gerade bekomme: Du brauchst eine 32-Bit-Nummer, die für das Gerät einzigartig ist? OK:

    1. Erstellen Sie die Nummer entweder zufällig oder durch Hashing der aktuellen Nanotime. Das bekommst du eine ziemlich einzigartige Saite, wie es ist.
    2. Dann frage den Server, ob diese Nummer bereits benutzt wurde. Wenn es hat, generiere die Nummer wieder und frage nochmal.

    Wenn Sie die Nanotime hash, ist es so praktisch unmöglich (nicht ganz unmöglich, Kollisionswiderstand ist nicht Kollisionsbeweis), um die gleiche Nummer zu bekommen. Angesichts der Rest Ihrer Saite, das würde es ganz einzigartig machen. Diese Methode erfordert keine Interaktionen mit dem Server, bis es tatsächlich den Server verwenden muss. Sagen Sie, dass der Client beim ersten Start nicht verbunden ist: generieren Sie die Nummer, speichern Sie sie, und wenn es eine Verbindung herstellt, bevor irgendetwas anderes passiert, überprüfen Sie, ob das Gerät vorhanden ist. Wenn es tut, von vorne anfangen. So bekommt man eine wirklich einzigartige Geräte-ID.

    Es gibt keine Möglichkeit, sicher zu wissen, dass die Schlüssel, die Sie auf dem Client generieren, auf der Server-DB eindeutig sind, bis Sie mit dem Server kommunizieren.

    Wenn Sie vor dem Server vor dem Server kommunizieren, bevor Sie Datensätze auf der Client-Seite erstellen, können Sie eine Reihe von Schlüsseln auf dem Server reservieren. Zum Beispiel könnte der Server Schlüssel in Chargen von 10.000 ausgeben. Der Client kommuniziert mit dem Server und behält den Beginn der nächsten Charge der verfügbaren Tasten, sagen wir 60.000. Der Kunde ist dann frei, Datensätze mit ids von 60.000 bis 69.999 zu erstellen. Sobald der Client keine Schlüssel mehr hat, muss er einen neuen Schlüsselbereich anfordern. Wenn alle Clients und der Server die Schlüssel für sich selbst behalten, dann sind alle generierten IDs in der Datenbank des Servers eindeutig.

    Nun, wenn Sie Datensätze auf der Client-Seite erstellen, bevor Sie mit dem Server kommunizieren, dann würden Sie stecken, um diese ids zu korrigieren, sobald Sie einen reservierten Bereich von dem Server erhalten, so dass sie innerhalb dieses Bereichs sind, bevor Sie diese Datensätze auf den Server synchronisieren .

    Ich bin mir nicht sicher, warum Sie auch versuchen, eine Client-ID in den Schlüssel aufzunehmen; Der Server verleiht den hohen Wert, und das reicht aus, um auf dem Client generierte Schlüssel zu erhalten.

    Aus meiner Erfahrung: Verwenden Sie lokale IDs auf dem Gerät und separate IDs auf dem Server . Jedes Mal, wenn Sie Daten über den Draht kommunizieren, konvertieren von einem zum anderen. Dies wird tatsächlich klären den Prozess und erleichtern Debugging. Die Umwandlungsroutinen bleiben klein, sind gut isoliert und stellen ein natürliches Element in der Anwendungsarchitektur dar. Die Daten, die über den Draht reisen, werden voraussichtlich relativ klein sein, jedenfalls und die ID-Umwandlung wird kein großer Overhead sein. Außerdem ist die Menge an Daten, die auf dem mobilen Gerät gehalten wird, vermutlich klein (die Masse ist auf dem Server).

    Ich schlage vor, die Umwandlung auf dem Gerät mit einer einfachen Tabelle local_ID <-> server_ID zu machen . Der Server sollte nur eine Prozedur angeben: einen Batch von Schlüsseln erzeugen, sagen wir 444 neue Schlüssel, die vermutlich das mobile Gerät dann seinen lokalen IDs zuordnen und Daten nur mit server_IDs an den Server senden. Die Umwandlungstabelle kann gelegentlich von unbenutzten IDs gelöscht werden, und lokale IDs können wiederverwendet werden, 32-Bit-Integer werden definitiv ausreichen.

    Motivation

    Die Tische bleiben klein, die Implementierung bleibt optimal für die native Gerätearchitektur, isoliert von unvorhersehbaren architektonischen Veränderungen an anderer Stelle und es gibt einen schönen Punkt für Debugging und Tracing, durch die alle Daten vergehen.

    Ich hatte eine Anwendung regenerieren alle IDs auf jeder Datendatei speichern und laden. Es war unerwartet einfach, schnell und eröffnete elegante andere Möglichkeiten wie ID-Space Defragmentierung und Konsolidierung.

    In Ihrem Fall können Sie die Server-Technologie mit minimalen Änderungen an der Client-Anwendung ändern. Da der Client sowieso offline betrieben werden kann, kann er nur die lokalen IDs in den meisten Funktionen nutzen. Nur das Synchronisationsmodul würde die Server-IDs abrufen und umwandeln.

    Ich bot zwei Bounties auf diese Frage und fand nicht die Antwort, die ich suche. Aber ich habe einige Zeit damit verbracht, über die beste Lösung nachzudenken, und vielleicht war die Frage nicht offen genug und konzentrierte sich auf die Lösung, die ich im Sinn hatte.

    Allerdings gibt es eine Menge von verschiedenen Strategien zur Verfügung, jetzt (nach der zweiten Bounty) Ich denke, die erste Frage zu beantworten ist, welche Datenmodell (s) haben Sie in Ihrem verteilten Umfeld? Vielleicht hast du

    1. Das gleiche (oder eine Teilmenge) Datenmodell auf Client und Server
    2. Differnet-Client-Datenmodell und Server-Datenmodell

    Wenn Sie mit 1) antworten, dann können Sie sich für Ihre Schlüsselstrategie entscheiden

    • Mit GUID verwenden
    • Mit meinem Ansatz High / Low
    • Mapping-Schlüssel als @ user3603546 vorgeschlagen

    Wenn du mit 2 antwortest, dann kommt mir nur noch folgendes vor:

    • Zusammengesetzte ID

    Ich habe nie Composite-IDs gemocht, aber wenn ich darüber nachdenke (und nennen Sie es nicht Composite-ID sowieso), dann könnte es eine mögliche Lösung sein. Im Folgenden möchte ich diese Lösung skizzieren:

    Glossar:

    • <Client key> … Primärschlüssel auf der Client-Seite generiert, so dass der Client wählt die Umsetzung (lange _id für Android)
    • <Server key> … Primärschlüssel auf der Serverseite generiert, so dass der Server die Implementierung wählt
    • <Client id> … ID zum Identifizieren des Clients
    • <Device id> … ID zum Identifizieren des Gerätes gibt es eine 1-n-Beziehung zwischen Client und Gerät

    Lösung:

    • Verwenden Sie es nur, wenn Sie ein Client-Datenmodell und ein Server-Datenmodell haben
    • Das Client-Datenmodell hat die Felder
      • <Client key> primärschlüssel
      • <Server-Schlüssel> nullable Datenfeld
    • Das Server-Datenmodell hat die Felder
      • <Server key> als primärschlüssel
      • <Client key> nullable Datenfeld
      • <Client id> als obligatorisches Datenfeld zur Unterscheidung des Clients
    • Beim Synchronisieren von Server zu Client, fehlende <Client-Schlüssel> auf dem Client und markieren Eintrag als schmutzig (so dass die Client-ID kommt an den Server am Ende des Tages)
    • Beim Synchronisieren von Client zu Server, fehlende <Server-Taste> auf dem Server, bevor Sie es speichern
    • Die Zuordnung zwischen Client- und Server-Datenmodell kann durch spezialisierte Frameworks wie Planierraupen oder Orika abgewickelt werden, die Schlüsselgenerierung muss jedoch bei der Kartierung integriert werden.

    Ich habe diese Lösung nie gemocht, weil ich immer in Server-Datenmodell-Begriffe gedacht habe. Ich habe Entitäten, die nur auf dem Server leben und ich wollte immer diese Entitäten auf dem Client erstellen, was nicht möglich wäre. Aber wenn ich im Client-Datenmodell denke, könnte ich zB eine Entität haben. Produkt, das zu zwei Entitäten (Produkt und ein ClientProdukt) auf dem Server führt.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.