SnowFlake分散型自己増加ID--Zookeeperベースのクラスタ実装
分散システムでは、グローバル一意のIDが必要なシーンがありますが、IDの競合を防ぐために一般的には発信器が使用されます
最も簡単な方法はUUIDを採用することであるが、UUIDは無秩序である.
分布式id生成アルゴリズムには多くの種類があり、TwitterのSnowFlakeはその古典的なものであり、生成されたIDは全体的に秩序化されている.
例えば、mysqlクラスタは、クラスタ内で生成されるIDの一意性および秩序性を自己ステップ長で解決することができるが、クラスタ内でmysqlノードを追加削除する場合、すべてのmysqlノードの自己ステップ長を調整する必要がある.
SnowFlakeの原理の紹介について,分布id生成アルゴリズムSnowFlakeを理解するために文章を参照することができる.
依然として国際的な慣例で、まずコードSnowFlakeWithZKをアップします
SnowFlakeWithZKでは、簡単に発号器クラスタを構築し、ZookeeperでworkIdを管理することで、クラスタノードの構成を頻繁に変更する手間を省くことができます.
使用
インストール
SnowFlakeWithZK-1.0.1をダウンロードして解凍するzip
解凍ディレクトリに入り、
API GET http(s)://[host]:[port]/api/next/long長整数で を返す GET http(s)://[host]:[port]/api/next/hex 16進数で を返します. GET http(s)://[host]:[port]/api/next/binバイナリで を返します. GET http(s)://[host]:[port]/api/parse/long/{id}解析長整型id GET http(s)://[host]:[port]/api/parse/hex/{id}解析16進id スタンドアロン使用
クラスタ使用
zookeeperの使用
SnowFlakeWithZK ZookeeperによるworkIdの管理
zookeeperを使用しない
注意:クラスタ内の各SnowFlakeインスタンスのworkIdは、異なることを保証する必要があります.
RUN_ARGSパラメータ
--server.portサービスポート--machineId.DataCenter Idデータセンターid,0~31,デフォルト16--machineId.workerIdインスタンスid,0~31,デフォルト5,--zookeeper.Enable=falseの場合に有効になり、同じデータセンターの異なるインスタンスは、それぞれ異なる--zookeeperを保証する必要があります.enableはzookeeperを使用してworkerIdを管理するかどうか、デフォルトtrue--zookeeper.url zookeeper接続アドレス、デフォルトlocalhost:2181、--zookeeper.enable=trueで有効
ソース解析
プロジェクトはspringbootフレームワークを採用し、
構成
構成
このプロジェクトは、Spring Cloud、Dubboなどのマイクロサービスフレームワークに簡単にアクセスできます.このツールが役に立つ場合は、starを歓迎します.
最も簡単な方法はUUIDを採用することであるが、UUIDは無秩序である.
分布式id生成アルゴリズムには多くの種類があり、TwitterのSnowFlakeはその古典的なものであり、生成されたIDは全体的に秩序化されている.
例えば、mysqlクラスタは、クラスタ内で生成されるIDの一意性および秩序性を自己ステップ長で解決することができるが、クラスタ内でmysqlノードを追加削除する場合、すべてのmysqlノードの自己ステップ長を調整する必要がある.
SnowFlakeの原理の紹介について,分布id生成アルゴリズムSnowFlakeを理解するために文章を参照することができる.
依然として国際的な慣例で、まずコードSnowFlakeWithZKをアップします
SnowFlakeWithZKでは、簡単に発号器クラスタを構築し、ZookeeperでworkIdを管理することで、クラスタノードの構成を頻繁に変更する手間を省くことができます.
使用
インストール
SnowFlakeWithZK-1.0.1をダウンロードして解凍するzip
解凍ディレクトリに入り、
./SnowFlakeWithZK.jar start
を実行します.API
SnowFlakeWithZK.conf
のRUN_ARGS
パラメータを変更し、--zookeeper.enable=false
を追加クラスタ使用
zookeeperの使用
SnowFlakeWithZK.conf
のRUN_ARGS
パラメータを変更し、--zookeeper.enable=true --zookeeper.url=[zookeeper-host]:[zookeeper-port]
を追加SnowFlakeWithZK ZookeeperによるworkIdの管理
zookeeperを使用しない
SnowFlakeWithZK.conf
のRUN_ARGS
パラメータを変更し、--zookeeper.enable=false --machineId.workId=[You workId]
を追加注意:クラスタ内の各SnowFlakeインスタンスのworkIdは、異なることを保証する必要があります.
RUN_ARGSパラメータ
--server.portサービスポート--machineId.DataCenter Idデータセンターid,0~31,デフォルト16--machineId.workerIdインスタンスid,0~31,デフォルト5,--zookeeper.Enable=falseの場合に有効になり、同じデータセンターの異なるインスタンスは、それぞれ異なる--zookeeperを保証する必要があります.enableはzookeeperを使用してworkerIdを管理するかどうか、デフォルトtrue--zookeeper.url zookeeper接続アドレス、デフォルトlocalhost:2181、--zookeeper.enable=trueで有効
ソース解析
プロジェクトはspringbootフレームワークを採用し、
@ConditionalOnProperty
注釈でzookeeperを使用するかどうかを制御する.構成
zookeeper.enable
がfalse
である場合、構成中のmachineId.workId
によってworkerが起動する/**
* SnowFlake Machine ID
*
* zookeeper.enable = false
*/
@ConditionalOnProperty("zookeeper.enable", matchIfMissing = true, havingValue = "false")
@Configuration
class SingletonConfiguration {
private val logger = LoggerFactory.getLogger(SingletonConfiguration::class.java)
@Value("\${machineId.dataCenterId:16}")
private var dataCenterId: Long = 16
@Value("\${machineId.workerId:0}")
private var workerId: Long = 0
@Bean
fun idWorker(): IdWorker {
logger.info("Singleton Detected! Create IdWorker using SingletonConfiguration!")
return IdWorker(workerId, dataCenterId)
}
}
構成
zookeeper.enable
がtrue
である場合、構成中のzookeeper.url
によりzkが接続され、zkにおいて一時秩序ノードが作成され、ノードのシーケンス番号によりworkIdが制御される./**
* zookeeper SnowFlake Machine ID
*
* zookeeper.enable = true
*/
@ConditionalOnProperty("zookeeper.enable")
@Configuration
class ZKConfiguration {
private val logger = LoggerFactory.getLogger(ZKConfiguration::class.java)
@Value("\${zookeeper.url}")
private lateinit var url: String
@Value("\${machineId.datacenterId:16}")
private var dataCenterId: Long = 16
@Bean
@Primary
fun idWorker(): IdWorker {
logger.info("Zookeeper Detected! Create IdWorker using ZKConfiguration!")
val client = CuratorFrameworkFactory.builder()
.connectString(url)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(ExponentialBackoffRetry(1000, 3))
.build()
client.start()
val parent = "/snowflake/$dataCenterId"
val worker = "$parent/worker"
client.checkExists().forPath("/snowflake/$dataCenterId")
?: client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(parent)
// workerId
val name = client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(worker)
val workerId = name.substring(worker.length).toLong()
var idWorker = IdWorker(workerId, dataCenterId)
//
client.connectionStateListenable.addListener(ConnectionStateListener { _client: CuratorFramework, state: ConnectionState ->
when (state) {
ConnectionState.RECONNECTED -> {
val name = _client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(worker)
val workerId = name.substring(worker.length).toLong()
idWorker.workerId = workerId
logger.info("ZK ReConnected. workerId changed: $workerId")
}
ConnectionState.LOST, ConnectionState.SUSPENDED -> {
logger.warn("ZK is Abnormal. State is $state")
}
else -> {
logger.info("ZK State Changed: $state")
}
}
})
return idWorker
}
}
このプロジェクトは、Spring Cloud、Dubboなどのマイクロサービスフレームワークに簡単にアクセスできます.このツールが役に立つ場合は、starを歓迎します.