Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
スケールするシステムにお
けるエンティティの扱いと
分散ID生成
安田裕介
ChatWork
2016/03/26
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved.
アジェンダ
• エンティティとは何か
• エンティティの何が難しいのか
• エンティティの難しさ...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 3
エンティティ
• 一意に識別できるオブジェクト
• ユーザー、メッセージなど
• IDを持つ...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 4
エンティティは変化するから難しい
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 5
エンティティと素直に付き合っている
とシステムはスケールしない
記憶デバイス、ファイルシステ...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved.
ドメインイベントによるEvent Sourcing
• 不変のイベントだけで状態を管理する手法に...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 7
エンティティをアクターで表現して
Event Sourcingする
• エンティティの状態を...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 8
エンティティアクターの実装
class MessageEntity(messageId: M...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 9
エンティティのIDは誰が決める?
• Event SourcingではエンティティはDBに存...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved.
分散ID生成器: Twitter Snowflake
• システムをスケールさせるには、従来の中...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 11
ChatworkのID生成器
Scalaを用いて分散IDワーカを実装する PHPでID生成...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 12
ID生成アクターを作ってみる
class IdWorker(dcId: Datacente...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved.
エンティティ(分散ID生成器)の一意
性をどう保証するか
• エンティティはシステムに複数存在し...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 14
エンティティの一意性を保証する手法
シャーディング
Shard Coordinator
S...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 15
シャーディングに対応した分散ID生成器のソースコード
https://github.com...
スケールするシステムにおけるエンティティの扱いと分散ID生成
2016/03/26 © ChatWork All rights reserved. 16
まとめ
•エンティティは一意に識別できるオブジェクト
•エンティティは状態が変わり続けるか...
Nächste SlideShare
Wird geladen in …5
×

スケールするシステムにおけるエンティティの扱いと 分散ID生成

2.073 Aufrufe

Veröffentlicht am

Scala将軍達の後の祭りLT

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

スケールするシステムにおけるエンティティの扱いと 分散ID生成

  1. 1. スケールするシステムにお けるエンティティの扱いと 分散ID生成 安田裕介 ChatWork 2016/03/26
  2. 2. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. アジェンダ • エンティティとは何か • エンティティの何が難しいのか • エンティティの難しさの解決策:Event Sourcing • アクターとエンティティ • エンティティのIDの分散発行方法 • エンティティの一意性の保証:シャーディング 2
  3. 3. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 3 エンティティ • 一意に識別できるオブジェクト • ユーザー、メッセージなど • IDを持つ • 同一エンティティの状態は変わり続ける • e.g. メッセージは編集されたり消されたりする • ドメインイベントやコマンドもエンティティ(不変)
  4. 4. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 4 エンティティは変化するから難しい
  5. 5. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 5 エンティティと素直に付き合っている とシステムはスケールしない 記憶デバイス、ファイルシステム、データベース、アーキテクチャは スケールするためにイミュータブルになっていく ミュータブルなエンティティの状態をインフラストラク チャに永続化しない方法を考えないといけない Immutability Changes Everything Designing Data-Intensive Applications
  6. 6. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. ドメインイベントによるEvent Sourcing • 不変のイベントだけで状態を管理する手法にEvent Sourcingがある • エンティティの状態が変更された時ドメインイベントが 起きる • 不変のドメインイベントの歴史があればエンティティの 状態が復元できる • ドメインイベントだけ永続化すれば追記のみにできる 6 未読+1 未読+1 未読-1 未読+1 未読-1 未読+1 未読件数2 ドメインイベントの歴史 エンティティ の状態
  7. 7. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 7 エンティティをアクターで表現して Event Sourcingする • エンティティの状態をアクターの内部に隔離する • コマンドメッセージを受け取ったらドメインイベントを永続化してエン ティティの状態を変更 • アクターは状態や位置、障害を隠蔽するので、外からは無限の寿命を持 つオブジェクトのように見える Akka Persistence and Eventuate Akka Persistenceはアクターで Event Sourcingを行う実装の1つ
  8. 8. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 8 エンティティアクターの実装 class MessageEntity(messageId: MessageId, roomId: ChatRoomId) extends PersistentActor with ActorLogging { import MessageProtocol._ override def persistenceId: String = Message.persistenceId(messageId, roomId) var messageState: Message = _ def receiveCommand: Receive = { case Commands.PostMessage(id, roomId, message, createdAt) => { val p = Message.postMessage(id, roomId, message, createdAt) persist(MessagePosted(p)) { event => updateState(MessagePosted(p)) context.system.eventStream.publish(MessagePosted(p)) } } case Commands.DeleteMessage(id, roomId, deletedAt) => { val e = messageState.deleteMessage(deletedAt) persist(MessageDeleted(e)) { event => updateState(MessageDeleted(e)) saveSnapshot(messageState) context.system.eventStream.publish(MessageDeleted(e)) } } } def receiveRecover: Receive = { case event: MessagePosted => updateState(event) case event: MessageDeleted => updateState(event) } def updateState(event: MessageProtocol.Event): Unit = event match { case MessagePosted(newMessage) => messageState = newMessage case MessageDeleted(deletedMessage) => messageState = deletedMessage } }
  9. 9. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 9 エンティティのIDは誰が決める? • Event SourcingではエンティティはDBに存在しない • エンティティはシステムに存在する • IDの発行をDBに任せられない • そもそも分散DBは連番IDを発行できない
  10. 10. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 分散ID生成器: Twitter Snowflake • システムをスケールさせるには、従来の中央集権的なDB によるID生成ではなく、分散独立したID生成が必要にな る • Snowflakeは分散ID生成サービス • Twitter社がMySQLからCassandraに移行した時に作られ た • https://github.com/twitter/snowflake 10
  11. 11. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 11 ChatworkのID生成器 Scalaを用いて分散IDワーカを実装する PHPでID生成器を実装してみました
  12. 12. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 12 ID生成アクターを作ってみる class IdWorker(dcId: DatacenterId, wId: WorkerId) extends Actor with IdWorkerImpl with ActorLogging { import IdWorkerProtocol._ val datacenterId: Long = dcId.value val workerId: Long = wId.value var sequenceId: Long = 0L var lastTimestamp = -1L def receive: Receive = { case msg@GenerateId(replyTo) => { val NextId(idOpt, timestamp, nextSequence) = nextId(timeGen(), lastTimestamp, sequenceId) sequenceId = nextSequence lastTimestamp = timestamp idOpt match { case Some(id) => replyTo ! IdGenerated(id) case None => { log.debug("retrying to avoid id duplication") self ! msg } } } } } ID生成のアルゴリズムは同じ 状態をアクター内に閉じ込めて同期コードを排除 時間分解能を超えた時にブロックしない 1つのIdWorkerでおよそ40k/secのIDを生成可能 ソースコード
  13. 13. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. エンティティ(分散ID生成器)の一意 性をどう保証するか • エンティティはシステムに複数存在してはならない • 複数存在すると同時に異なるドメインイベントが発行さ れ矛盾した状態になる • ID生成器もエンティティで、同じIDのものが複数存在し てはならない(重複したIDの発行につながる) • SnowflakeはZookeeperを使ってID生成器を管理している 13
  14. 14. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 14 エンティティの一意性を保証する手法 シャーディング Shard Coordinator Shard Region Shard Region Shard Region IdWorker-1 IdWorker-2 IdWorker-3 … IdWorker-30 IdWorker-31 IdWorker-32 … client GenerateId(workerId = 30) Node 1 Node N ID生成器とエンティティの一意性は同じ手法で実現可能
  15. 15. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 15 シャーディングに対応した分散ID生成器のソースコード https://github.com/TanUkkii007/reactive-snowflake
  16. 16. スケールするシステムにおけるエンティティの扱いと分散ID生成 2016/03/26 © ChatWork All rights reserved. 16 まとめ •エンティティは一意に識別できるオブジェクト •エンティティは状態が変わり続けるから難しい •システムをスケールさせるためには不変なデータを扱う 必要がある •Event Sourcingをつかえば可変なエンティティではなく 不変なドメインイベントを永続化できる •DBに頼らずにエンティティのIDを発行する手法がある •システムレベルでエンティティの一意性を保証する技術 にシャーディングがある

×