O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
スケールするシステムにお
けるエンティティの扱いと
分散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
まとめ
•エンティティは一意に識別できるオブジェクト
•エンティティは状態が変わり続けるか...
Próximos SlideShares
Carregando em…5
×

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

2.072 visualizações

Publicada em

Scala将軍達の後の祭りLT

Publicada em: Tecnologia
  • Seja o primeiro a comentar

スケールするシステムにおけるエンティティの扱いと 分散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を発行する手法がある •システムレベルでエンティティの一意性を保証する技術 にシャーディングがある

×