Häufig verwendete verteilte ID-Lösungen
In einem verteilten System ist es sehr wichtig, eine weltweit eindeutige ID zu generieren In einem verteilten System kann es zu ID-Konflikten kommen, wenn mehrere Knoten gleichzeitig IDs generieren.
Im Folgenden werden einige häufig verwendete verteilte ID-Lösungen vorgestellt.
UUID
UUID (Universally Unique Identifier) ist eine aus 128 Ziffern bestehende Kennung, die weltweit Eindeutigkeit garantieren kann, da ihr Generierungsalgorithmus auf Zeitstempel, Knoten-ID und basiert andere Faktoren. UUID kann mit Javas eigener UUID-Klasse generiert werden, wie unten gezeigt:
javaCopy code import java.util.UUID; public class UuidGenerator { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); System.out.println(uuid.toString()); } }
Die von Javas eigener UUID-Klasse generierte UUID ist sehr einfach und benutzerfreundlich und erfordert keine zusätzliche Konfiguration und Verwaltung sein Vorteil. Aufgrund seiner Länge (128 Bit) eignet sich UUID nicht als Primärschlüssel für Datenbanktabellen und ist schwer zu sortieren und zu indizieren.
Snowflake
Snowflake ist ein von Twitter offener, verteilter ID-Generierungsalgorithmus. Er kann eine eindeutige 64-Bit-ID generieren, die Zeitstempel, Rechenzentrums-ID und Maschinen-ID enthält andere Informationen. Der Java-Code des Snowflake-Algorithmus lautet wie folgt:
Der Java-Code des Snowflake-Algorithmus:
javaCopy code public class SnowflakeGenerator { private final static long START_STMP = 1480166465631L; private final static long SEQUENCE_BIT = 12; private final static long MACHINE_BIT = 5; private final static long DATACENTER_BIT = 5; private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; private long machineId; private long sequence = 0L; private long lastStmp = -1L; public SnowflakeGenerator(long datacenterId, long machineId) { if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); } this.datacenterId = datacenterId; this.machineId = machineId; } public synchronized long nextId() { long currStmp = getNewstmp(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStmp == lastStmp) { sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0L) { currStmp = getNextMill(); } } else { sequence = 0L; } lastStmp = currStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT | datacenterId << DATACENTER_LEFT | machineId << MACHINE_LEFT | sequence; } private long getNextMill() { long mill = getNewstmp(); while (mill <= lastStmp) { mill = getNewstmp(); } return mill; } private long getNewstmp() { return System.currentTimeMillis(); } }
Die Vorteile des Snowflake-Algorithmus sind hohe Leistung bei der Generierung von IDs und kurze Die ID-Länge (64 Bit) kann als Primärschlüssel der Datenbanktabelle verwendet werden und eignet sich zum Sortieren und Indizieren. Es ist jedoch zu beachten, dass andere verteilte Algorithmen zur ID-Generierung erforderlich sind, wenn die Anzahl der Knoten im Cluster die Anzahl der von der Maschinen-ID belegten Ziffern übersteigt oder der Cluster sehr groß ist und die Anzahl der Zeitstempelziffern nicht ausreicht berücksichtigt werden.
Leaf
Leaf ist ein verteilter ID-Generierungsalgorithmus von Meituan Dianping, der eine weltweit eindeutige 64-Bit-ID generieren kann. Der Java-Code des Leaf-Algorithmus lautet wie folgt:
Der Java-Code des Leaf-Algorithmus:
javaCopy code public class LeafGenerator { private static final Logger logger = LoggerFactory.getLogger(LeafGenerator.class); private static final String WORKER_ID_KEY = "leaf.worker.id"; private static final String PORT_KEY = "leaf.port"; private static final int DEFAULT_PORT = 8080; private static final int DEFAULT_WORKER_ID = 0; private static final int WORKER_ID_BITS = 10; private static final int SEQUENCE_BITS = 12; private static final int MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1; private static final int MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1; private static final long EPOCH = 1514736000000L; private final SnowflakeIdWorker idWorker; public LeafGenerator() { int workerId = SystemPropertyUtil.getInt(WORKER_ID_KEY, DEFAULT_WORKER_ID); int port = SystemPropertyUtil.getInt(PORT_KEY, DEFAULT_PORT); this.idWorker = new SnowflakeIdWorker(workerId, port); logger.info("Initialized LeafGenerator with workerId={}, port={}", workerId, port); } public long nextId() { return idWorker.nextId(); } private static class SnowflakeIdWorker { private final long workerId; private final long port; private long sequence = 0L; private long lastTimestamp = -1L; SnowflakeIdWorker(long workerId, long port) { if (workerId < 0 || workerId > MAX_WORKER_ID) { throw new IllegalArgumentException(String.format("workerId must be between %d and %d", 0, MAX_WORKER_ID)); } this.workerId = workerId; this.port = port; } synchronized long nextId() { long timestamp = System.currentTimeMillis(); if (timestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (timestamp == lastTimestamp) { sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0L) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; return ((timestamp - EPOCH) << (WORKER_ID_BITS + SEQUENCE_BITS)) | (workerId << SEQUENCE_BITS) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } } }
Obwohl der Leaf-Algorithmus IDs etwas langsamer generiert als der Snowflake-Algorithmus, ist er Kann mehr Arbeitsknoten unterstützen. Die vom Leaf-Algorithmus generierte ID besteht aus drei Teilen, nämlich Zeitstempel, Worker-ID und Seriennummer. Der Zeitstempel belegt 42 Bit, die Worker-ID belegt 10 Bit und die Seriennummer belegt 12 Bit, also insgesamt 64 Bit.
Die oben genannten sind gängige verteilte ID-Generierungsalgorithmen. Natürlich gibt es auch andere Lösungen, wie zum Beispiel: MongoDB ID, UUID, Twitter Snowflake usw. Unterschiedliche Lösungen eignen sich für unterschiedliche Geschäftsszenarien, und auch die spezifischen Implementierungsdetails und die Leistung sind unterschiedlich. Sie müssen die geeignete Lösung basierend auf der tatsächlichen Situation auswählen.
Zusätzlich zu dem oben vorgestellten verteilten ID-Generierungsalgorithmus gibt es auch einige neue Lösungen für die verteilte ID-Generierung, beispielsweise den verteilten ID-Generierungsalgorithmus von Flicker, der ähnliche Ideen wie Snowflake verwendet, jedoch unterschiedliche Bitzuteilungsmethoden übernommen, was flexibler als Snowflake ist und die Anzahl der von jedem Teil belegten Bits je nach Bedarf dynamisch angepasst werden kann. Darüber hinaus hat Facebook auch die ID Generation Service (IGS)-Lösung eingeführt, die ID-Generierung und -Speicherung trennt und eine flexiblere und skalierbarere Lösung bietet, jedoch ein komplexeres Architekturdesign und eine komplexere Implementierung erfordert.
Je nach unterschiedlichen Geschäftsanforderungen können mehrere Sätze verteilter Lösungen zur ID-Generierung entworfen werden. Hier sind einige meiner persönlichen Vorschläge:
Basierend auf der automatischen Inkrementierungs-ID-Generierung der Datenbank: Die Verwendung der automatischen Inkrementierungs-ID der Datenbank als global eindeutige ID kann die Einzigartigkeit von sicherstellen Die ID ist einfach zu implementieren, kann jedoch bei hoher Parallelität zu Leistungsengpässen führen. Daher wird die Verwendung in Szenarien mit hoher Parallelität nicht empfohlen.
Basierend auf der UUID-Generierung: Die Verwendung von UUID als global eindeutige ID kann die Eindeutigkeit der ID sicherstellen, aber die ID-Länge ist lang (128 Bit) und unpraktisch Speicherung und Übertragung, und die Wahrscheinlichkeit doppelter IDs ist sehr gering, aber nicht 0. Es wird empfohlen, bei Verwendung eines verteilten Systems die ID-Länge sowie die Kosten für Speicherung und Übertragung zu berücksichtigen.
Basierend auf der Redis-Generierung: Mit der atomaren Operation von Redis kann die Eindeutigkeit der ID garantiert werden, und die Geschwindigkeit der ID-Generierung ist sehr schnell, was geeignet sein kann für Szenarien mit hoher Parallelität. Es ist zu beachten, dass ein Absturz oder eine schlechte Leistung von Redis die Effizienz und Verfügbarkeit der ID-Generierung beeinträchtigen kann.
Generiert basierend auf ZooKeeper: Die Verwendung des Seriennummerngenerators von ZooKeeper kann die Eindeutigkeit der ID sicherstellen, und die Implementierung ist relativ einfach, erfordert jedoch die Einführung zusätzlicher Abhängigkeiten und Ressourcen und es kann zu Leistungsengpässen kommen.
Um eine verteilte ID-Generierungslösung auszuwählen, die zu Ihrem Geschäftsszenario passt, müssen Sie die Einzigartigkeit der ID, Generierungsgeschwindigkeit, Länge, Speicherkosten, Skalierbarkeit usw. umfassend berücksichtigen. Verfügbarkeit usw. Mehrere Faktoren. Die Implementierung verschiedener Lösungen erfordert die Berücksichtigung von Kompromissen und Auswahlmöglichkeiten in tatsächlichen Situationen, da auch deren Implementierungsdetails und Leistung unterschiedlich sind.
Die detaillierte Code-Demo jeder Lösung ist unten angegeben:
Generieren Sie basierend auf der automatischen Inkrementierungs-ID der Datenbank
javaCopy code public class IdGenerator { private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test"; private static final String JDBC_USER = "root"; private static final String JDBC_PASSWORD = "password"; public long generateId() { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD); pstmt = conn.prepareStatement("INSERT INTO id_generator (stub) VALUES (null)", Statement.RETURN_GENERATED_KEYS); pstmt.executeUpdate(); rs = pstmt.getGeneratedKeys(); if (rs.next()) { return rs.getLong(1); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (rs != null) { rs.close(); } if (pstmt != null) { pstmt.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } return 0L; } }
Generieren Sie basierend auf der UUID#🎜 🎜#javaCopy code
import java.util.UUID;
public class IdGenerator {
public String generateId() {
return UUID.randomUUID().toString().replace("-", "");
}
}
Generiert basierend auf RedisjavaCopy code
import redis.clients.jedis.Jedis;
public class IdGenerator {
private static final String REDIS_HOST = "localhost";
private static final int REDIS_PORT = 6379;
private static final String REDIS_PASSWORD = "password";
private static final int ID_GENERATOR_EXPIRE_SECONDS = 3600;
private static final String ID_GENERATOR_KEY = "id_generator";
public long generateId() {
Jedis jedis = null;
try {
jedis = new Jedis(REDIS_HOST, REDIS_PORT);
jedis.auth(REDIS_PASSWORD);
long id = jedis.incr(ID_GENERATOR_KEY);
jedis.expire(ID_GENERATOR_KEY, ID_GENERATOR_EXPIRE_SECONDS);
return id;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
return 0L;
}
}
Generiert basierend auf ZooKeeperjavaCopy code
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class IdGenerator implements Watcher {
private static final String ZK_HOST = "localhost";
private static final int ZK_PORT = 2181;
private static final int SESSION_TIMEOUT = 5000;
private static final String ID_GENERATOR_NODE = "/id_generator";
private static final int ID_GENERATOR_EXPIRE_SECONDS = 3600;
private long workerId = 0;
public IdGenerator() {
try {
ZooKeeper zk = new ZooKeeper(ZK_HOST + ":" + ZK_PORT, SESSION_TIMEOUT, this);
CountDownLatch latch = new CountDownLatch(1);
latch.await();
if (zk.exists(ID_GENERATOR_NODE, false) == null) {
zk.create(ID_GENERATOR_NODE, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
workerId = zk.getChildren(ID_GENERATOR_NODE, false).size();
zk.create(ID_GENERATOR_NODE + "/worker_" + workerId, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (Exception e) {
e.printStackTrace();
}
}
public long generateId() {
ZooKeeper zk = null;
try {
zk = new ZooKeeper(ZK_HOST + ":" + ZK_PORT, SESSION_TIMEOUT, null);
CountDownLatch latch = new CountDownLatch(1);
latch.await();
zk.create(ID_GENERATOR_NODE + "/id_", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, (rc, path, ctx, name) -> {}, null);
byte[] data = zk.getData(ID_GENERATOR_NODE + "/worker_" + workerId, false, null);
long id = Long.parseLong(new String(data)) * 10000 + zk.getChildren(ID_GENERATOR_NODE, false).size();
return id;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (zk != null) {
try {
zk.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return 0L;
}
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected) {
System.out.println("Connected to ZooKeeper");
CountDownLatch latch = new CountDownLatch(1);
latch.countDown();
}
}
}
Beachten Sie, dass die temporären Knoten von ZooKeeper hier verwendet werden, um verschiedene Arbeitsknoten zu koordinieren Wenn der Knoten auflegt, werden auch seine temporären Knoten gelöscht, wodurch sichergestellt wird, dass die von jedem Arbeitsknoten erhaltene ID eindeutig ist. Das obige ist der detaillierte Inhalt vonWelche Lösungen gibt es für die verteilte Redis-ID?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Redis sticht aufgrund seiner hohen Geschwindigkeit, Vielseitigkeit und reichhaltigen Datenstruktur auf. 1) Redis unterstützt Datenstrukturen wie Zeichenfolgen, Listen, Sammlungen, Hashs und geordnete Sammlungen. 2) Es speichert Daten über den Speicher und unterstützt RDB und AOF Persistenz. 3) Ausgehend von Redis 6.0 wurden Multi-Thread-E/A-Operationen eingeführt, was die Leistung in hohen Parallelitätsszenarien verbessert hat.

RedisiscassifizedasanosqldatabaseBecauseituseSakey-valuedatamodelinSteAfThetitionalrelationalDatabasemodel

Redis verbessert die Anwendungsleistung und die Skalierbarkeit, indem sie Daten zwischengespeichert und verteilte Verriegelung und Datenpersistenz implementiert. 1) Cache -Daten: Verwenden Sie Redis, um häufig auf Daten zugegriffen, um die Geschwindigkeit des Datenzugriffs zu verbessern. 2) Verteilte Schloss: Verwenden Sie Redis, um verteilte Sperren zu implementieren, um die Sicherheit des Betriebs in einer verteilten Umgebung zu gewährleisten. 3) Datenpersistenz: Stellen Sie die Datensicherheit durch RDB- und AOF -Mechanismen sicher, um den Datenverlust zu verhindern.

Das Datenmodell und die Struktur von Redis umfassen fünf Haupttypen: 1. String: Verwendet, um Text oder binäre Daten zu speichern, und unterstützt Atomoperationen. 2. Liste: Bestellte Elementssammlung, geeignet für Warteschlangen und Stapel. 3. SET: Ungeordnete einzigartige Elemente, unterstützende Set -Operation. V. 5. Hash Table (Hash): Eine Sammlung von Schlüsselwertpaaren, die zum Speichern von Objekten geeignet sind.

Die Datenbankmethoden von Redis umfassen In-Memory-Datenbanken und Schlüsselwertspeicher. 1) Redis speichert Daten im Speicher und liest und schreibt schnell. 2) Es wird Schlüsselwertpaare verwendet, um Daten zu speichern, unterstützt komplexe Datenstrukturen wie Listen, Sammlungen, Hash-Tabellen und geordnete Sammlungen, die für Caches und NoSQL-Datenbanken geeignet sind.

Redis ist eine leistungsstarke Datenbanklösung, da sie eine schnelle Leistung, umfangreiche Datenstrukturen, hohe Verfügbarkeit und Skalierbarkeit, Persistenzfunktionen und eine breite Palette von Ökosystemunterstützung bietet. 1) Extrem schnelle Leistung: Die Daten von Redis werden im Speicher gespeichert und verfügt über extrem schnelle Lesen und Schreibgeschwindigkeiten, die für Anwendungen mit hoher Parallelität und niedriger Latenz geeignet sind. 2) Reiche Datenstruktur: Unterstützt mehrere Datentypen wie Listen, Sammlungen usw., die für eine Vielzahl von Szenarien geeignet sind. 3) hohe Verfügbarkeit und Skalierbarkeit: Unterstützt die Master-Slave-Replikation und den Clustermodus, um eine hohe Verfügbarkeit und horizontale Skalierbarkeit zu erzielen. 4) Persistenz und Datensicherheit: Die Datenpersistenz werden durch RDB und AOF erreicht, um die Integrität und Zuverlässigkeit der Daten zu gewährleisten. 5) Weites Ökosystem und Unterstützung der Gemeinschaft: mit einem riesigen Ökosystem und einer aktiven Gemeinschaft.

Zu den wichtigsten Merkmalen von Redis gehören Geschwindigkeit, Flexibilität und Reich Datenstrukturunterstützung. 1) Geschwindigkeit: Redis ist eine In-Memory-Datenbank, und Lese- und Schreibvorgänge sind fast augenblicklich und für Cache und Sitzungsverwaltung geeignet. 2) Flexibilität: Unterstützt mehrere Datenstrukturen wie Zeichenfolgen, Listen, Sammlungen usw., die für die komplexe Datenverarbeitung geeignet sind. 3) Unterstützung bei der Datenstruktur: Bietet Zeichenfolgen, Listen, Sammlungen, Hash -Tabellen usw., die für unterschiedliche Geschäftsanforderungen geeignet sind.

Die Kernfunktion von Redis ist ein Hochleistungs-In-Memory-Datenspeicher- und Verarbeitungssystem. 1) Hochgeschwindigkeitsdatenzugriff: Redis speichert Daten im Speicher und bietet Lese- und Schreibgeschwindigkeit auf Mikrosekunden. 2) Reiche Datenstruktur: Unterstützt Zeichenfolgen, Listen, Sammlungen usw. und passt an eine Vielzahl von Anwendungsszenarien. 3) Persistenz: Behalten Sie Daten an, um durch RDB und AOF zu diskutieren. 4) Abonnement veröffentlichen: Kann in Nachrichtenwarteschlangen oder Echtzeit-Kommunikationssystemen verwendet werden.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Dreamweaver Mac
Visuelle Webentwicklungstools

Herunterladen der Mac-Version des Atom-Editors
Der beliebteste Open-Source-Editor

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

MinGW – Minimalistisches GNU für Windows
Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.