一般的に使用される分散 ID ソリューション
分散システムでは、グローバルに一意の ID を生成することが非常に重要です。分散システムでは複数のノードが存在するためです。同時に ID を生成すると、ID の競合が発生する可能性があります。
次に、一般的に使用される分散 ID ソリューションをいくつか紹介します。
UUID
UUID (Universally Unique Identifier) は 128 桁で構成される識別子で、その生成アルゴリズムはタイムスタンプ、ノード ID などの要素に基づいているため、グローバルな一意性を保証できます。 UUID は、以下に示すように、Java 独自の UUID クラスを使用して生成できます:
javaCopy code import java.util.UUID; public class UuidGenerator { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); System.out.println(uuid.toString()); } }
Java 独自の UUID クラスによって生成された UUID は非常にシンプルで使いやすく、追加の構成や管理を必要としません。 。 UUID はその長さ (128 ビット) のため、データベース テーブルの主キーとしては適しておらず、並べ替えやインデックス付けが困難です。
Snowflake
Snowflake は、Twitter がオープンソース化した分散 ID 生成アルゴリズムで、タイムスタンプ、データセンター ID、マシン ID などの情報を含む 64 ビットの一意の ID を生成できます。 Snowflake アルゴリズムの Java コードは次のとおりです。
Snowflake アルゴリズムの Java コード:
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(); } }
Snowflake アルゴリズムの利点は、ID 生成のパフォーマンスが高く、ID の長さが短いことです (64 bits) をデータベース テーブルの主キーとして使用すると、並べ替えとインデックス付けが容易になります。ただし、クラスター内のノードの数がマシン ID が占める桁数を超える場合、またはクラスターが非常に大きくタイムスタンプの桁数が十分でない場合は、他の分散 ID 生成アルゴリズムを使用する必要があることに注意してください。考慮されます。
Leaf
Leaf は、Meituan Dianping によってオープンソース化された分散 ID 生成アルゴリズムであり、グローバルに一意の 64 ビット ID を生成できます。 Leaf アルゴリズムの Java コードは次のとおりです。
Leaf アルゴリズムの Java コード:
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; } } }
Leaf アルゴリズムは、Snowflake アルゴリズムよりも ID の生成がわずかに遅くなりますが、より多くのワーカーをサポートできます。ノード 。 Leaf アルゴリズムで生成される ID は、タイムスタンプ、ワーカー ID、シーケンス番号の 3 つの部分で構成され、タイムスタンプが 42 ビット、ワーカー ID が 10 ビット、シーケンス番号が 12 ビットの合計 64 ビットを占めます。
上記は一般的な分散 ID 生成アルゴリズムですが、もちろん、MongoDB ID、UUID、Twitter Snowflake など、他のソリューションもあります。ビジネスシーンに応じて適したソリューションが異なり、具体的な実装内容やパフォーマンスも異なるため、実際の状況に応じて適切なソリューションを選択する必要があります。
上記で紹介した分散 ID 生成アルゴリズムに加えて、Flicker の分散 ID 生成アルゴリズムなど、新しい分散 ID 生成ソリューションもいくつか登場しています。これは、Snowflake と同様のアイデアを使用しますが、異なるビット割り当て方法を採用しています。 Snowflake よりも柔軟性があり、各部分が占めるビット数は必要に応じて動的に調整できます。さらに、Facebook は ID 生成サービス (IGS) ソリューションも開始しました。これは ID の生成と保存を分離し、より柔軟でスケーラブルなソリューションを提供しますが、より複雑なアーキテクチャの設計と実装が必要になります。
さまざまなビジネス ニーズに応じて、複数セットの分散 ID 生成ソリューションを設計できます。私の個人的な提案をいくつか紹介します。
データベース自動インクリメント ID に基づいて生成する: データベース自動インクリメント ID をグローバルに一意な ID として使用すると、ID の一意性が確保され、簡単になります。ただし、同時実行性が高いとパフォーマンスのボトルネックが発生する可能性があります。したがって、同時実行性の高いシナリオで使用することはお勧めできません。
UUID に基づいて生成: グローバルに一意な ID として UUID を使用すると、ID の一意性を確保できますが、ID の長さが長く (128 ビット)、保管や保存に不便です。 ID が重複する可能性は非常に低いですが、0 ではありません。分散システムを使用する場合は、ID の長さと、保存および送信のコストを考慮する必要があることが推奨されます。
Redis に基づく生成: Redis のアトミック操作を使用すると、ID の一意性が保証され、ID 生成速度が非常に高速になるため、同時実行性の高いシナリオに適用できます。 Redis がクラッシュしたり、パフォーマンスが低下したりすると、ID 生成の効率と可用性に影響が出る可能性があることに注意してください。
ZooKeeper に基づく生成: ZooKeeper のシリアル番号ジェネレーターを使用すると、ID の一意性を確保でき、実装は比較的簡単ですが、追加の依存関係とリソースの導入が必要です。パフォーマンスの問題がボトルネックになっている可能性があります。
ビジネス シナリオに合った分散 ID 生成ソリューションを選択するには、ID の一意性、生成速度、長さ、ストレージ コスト、拡張性、可用性などの複数の要素を総合的に考慮する必要があります。異なるソリューションを実装するには、実装の詳細やパフォーマンスも異なるため、実際の状況でのトレードオフと選択を考慮する必要があります。
各ソリューションの詳細なコード デモを以下に示します。
データベース自動インクリメント ID に基づいて生成
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; } }
UUID に基づいて生成
javaCopy code import java.util.UUID; public class IdGenerator { public String generateId() { return UUID.randomUUID().toString().replace("-", ""); } }
Generate Redis に基づいて
javaCopy 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; } }
ZooKeeper に基づいて生成
javaCopy 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(); } } }
ZooKeeper の一時ノードは、各作業ノードを調整するためにここで使用されることに注意してください。作業ノードがハングアップすると、その一時ノードも削除されます。各ワーカー ノードによって取得される ID が固有であることを確認します。
以上がRedis 分散 ID のソリューションは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

redisisclassifiedsaNosqldatabasebasesakey-valuedataModelinsteaded ofthetraditionaldatabasemodel.itoffersspeedand andffficability、makingidealforreal-timeaplications andcaching、butmaynotbesbesutable fors cenariois requiring datientiantientioniity

Redisは、データをキャッシュし、分散ロックとデータの持続性を実装することにより、アプリケーションのパフォーマンスとスケーラビリティを向上させます。 1)キャッシュデータ:Redisを使用して頻繁にアクセスしたデータをキャッシュして、データアクセス速度を向上させます。 2)分散ロック:Redisを使用して分散ロックを実装して、分散環境での操作のセキュリティを確保します。 3)データの持続性:データの損失を防ぐために、RDBおよびAOFメカニズムを介してデータセキュリティを確保します。

Redisのデータモデルと構造には、5つの主要なタイプが含まれます。1。文字列:テキストまたはバイナリデータの保存に使用され、原子操作をサポートします。 2。リスト:キューとスタックに適した注文された要素コレクション。 3.セット:順序付けられていない一意の要素セット、セット操作をサポートします。 4。注文セット(sortedset):ランキングに適したスコアを持つ一意の要素セット。 5。ハッシュテーブル(ハッシュ):オブジェクトの保存に適したキー価値ペアのコレクション。

Redisのデータベースメソッドには、メモリ内データベースとキー価値ストレージが含まれます。 1)Redisはデータをメモリに保存し、速く読み取り、書き込みます。 2)キー価値のペアを使用してデータを保存し、キャッシュやNOSQLデータベースに適したリスト、コレクション、ハッシュテーブル、注文コレクションなどの複雑なデータ構造をサポートします。

Redisは、高速パフォーマンス、リッチデータ構造、高可用性とスケーラビリティ、持続性能力、幅広いエコシステムサポートを提供するため、強力なデータベースソリューションです。 1)非常に速いパフォーマンス:Redisのデータはメモリに保存され、非常に速い読み取り速度と書き込み速度が高く、高い並行性と低レイテンシアプリケーションに適しています。 2)豊富なデータ構造:さまざまなシナリオに適したリスト、コレクションなど、複数のデータ型をサポートします。 3)高可用性とスケーラビリティ:マスタースレーブの複製とクラスターモードをサポートして、高可用性と水平スケーラビリティを実現します。 4)持続性とデータセキュリティ:データの整合性と信頼性を確保するために、データの持続性がRDBとAOFを通じて達成されます。 5)幅広い生態系とコミュニティのサポート:巨大なエコシステムとアクティブなコミュニティにより、

Redisの主な機能には、速度、柔軟性、豊富なデータ構造のサポートが含まれます。 1)速度:Redisはメモリ内データベースであり、読み取り操作はほとんど瞬間的で、キャッシュとセッション管理に適しています。 2)柔軟性:複雑なデータ処理に適した文字列、リスト、コレクションなど、複数のデータ構造をサポートします。 3)データ構造のサポート:さまざまなビジネスニーズに適した文字列、リスト、コレクション、ハッシュテーブルなどを提供します。

Redisのコア関数は、高性能のメモリ内データストレージおよび処理システムです。 1)高速データアクセス:Redisはデータをメモリに保存し、マイクロ秒レベルの読み取り速度と書き込み速度を提供します。 2)豊富なデータ構造:文字列、リスト、コレクションなどをサポートし、さまざまなアプリケーションシナリオに適応します。 3)永続性:RDBとAOFを介してディスクにデータを持続します。 4)サブスクリプションを公開:メッセージキューまたはリアルタイム通信システムで使用できます。

Redisは、次のようなさまざまなデータ構造をサポートしています。1。文字列、単一価値データの保存に適しています。 2。キューやスタックに適したリスト。 3.非重複データの保存に使用されるセット。 4。ランキングリストと優先キューに適した注文セット。 5。オブジェクトまたは構造化されたデータの保存に適したハッシュテーブル。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。
