Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

サンプルで学ぶCassandraアプリケーションの作り方

913 views

Published on

Cassandra Summit Tokyo 2017 スライド

Published in: Technology
  • Be the first to comment

  • Be the first to like this

サンプルで学ぶCassandraアプリケーションの作り方

  1. 1. サンプルで学ぶ Cassandraアプリケーションの 作り方 Cassandra Summit Tokyo 2017 森下 雄貴 (DataStax Japan合同会社)
  2. 2. スピーカー 森下 雄貴 (yuki@datastax.com) - Solution Architect (ときどきSoftware Developer) @ DataStax - Apache Cassandra™コミッター © DataStax, All Rights Reserved.2
  3. 3. Apache Cassandra™ を使ってスケーラブルなアプリケー ションを作りたい! - サンプルアプリケーションがあることを知ってもらう。 - Apache Cassandraデータモデリングの概要を知る。 - ドライバーの使い方を知る。 © DataStax, All Rights Reserved.3 今日の目標
  4. 4. KillrVideo © DataStax, All Rights Reserved.4 https://killrvideo.github.io/
  5. 5. KillrVideo Apache Cassandra™ / DataStax Enterprise リファレンスアプリケーション – https://killrvideo.github.io – オープンソース (APLv2) – スケーラブルなマイクロサービスアーキテクチャ • サービスは Node.js/C#/Java の各言語で実装 – データベース層はApache Cassandra / DSE • データモデリングのサンプル • ドライバーの利用サンプル 5 © DataStax, All Rights Reserved.
  6. 6. KillrVideo © DataStax, All Rights Reserved.6
  7. 7. KillrVideo 各層がスケーラブル 7 KillrVideo Web アプリケーション (node.js) KillrVideo マイクロサービス Apache Cassandra / DataStax Enterprise © DataStax, All Rights Reserved.
  8. 8. KillrVideo デモ環境 8 KillrVideo Web アプリケーション KillrVideo マイクロサービス Apache Cassandra / DataStax Enterprise 1ノード etcd: サービスディスカバリー サンプルデータ生成アプリ © DataStax, All Rights Reserved.
  9. 9. 利用している技術 - Docker - 各構成要素(Web/サービス/DB)をコンテナ化 - node.js - フロントエンドWebアプリケーション - React/Redux/Falcor - マイクロサービスの一つの実装言語 - gRPC - サービスのインターフェース定義 - Java - Spring Frameworkを利用してサービスを実装 - DataStax Enterprise - Apache Cassandraをコアとしたデータベース © DataStax, All Rights Reserved.9
  10. 10. タスク: コメント機能を作る © DataStax, All Rights Reserved.10
  11. 11. タスク: コメント機能を作る - コメント機能の概要 - ユーザーが動画にコメントを書く - 各動画のページにその動画に書かれたコメントを新着順に表示する - ユーザーは自分が投降したコメントをユーザーのページで見ることができる © DataStax, All Rights Reserved.11
  12. 12. API CommentService コメント用のサービス - commentOnVideo - 動画に紐づくコメントを登録する - getCommentsByVideo - 動画に紐づくコメントを取得する - getCommentsByUser - ユーザーに紐づくコメントを取得する © DataStax, All Rights Reserved.12
  13. 13. gRPCサービスの定義 // Manages comments service CommentsService { // Add a new comment to a video rpc CommentOnVideo(CommentOnVideoRequest) returns (CommentOnVideoResponse); // Get comments made by a user rpc GetUserComments(GetUserCommentsRequest) returns (GetUserCommentsResponse); // Get comments made on a video rpc GetVideoComments(GetVideoCommentsRequest) returns (GetVideoCommentsResponse); } © DataStax, All Rights Reserved.13
  14. 14. データモデリング © DataStax, All Rights Reserved.14
  15. 15. コメント機能のデータモデリング 概念データ モデル アプリケー ションワー クフロー マッピング 論理データ モデル 最適化 物理データ モデル Cassandraデータモデリングの流れ © DataStax, All Rights Reserved.15
  16. 16. Cassandraデータモデリングの原則 データを知る クエリを知る 非正規化 – データをネストする – データを重複して持つ © DataStax, All Rights Reserved.16
  17. 17. データを知る 概念データモデル / ERD © DataStax, All Rights Reserved.17 ユーザー 動画コメント する m n id 名前 … コメント タイムス タンプ id タイトル …
  18. 18. クエリを知る アプリケーションワークフロー © DataStax, All Rights Reserved.18
  19. 19. クエリを知る © DataStax, All Rights Reserved.19 動画に紐づくコメントを 取得する Q2 ユーザーに紐づくコメントを 取得する Q1 コメントサービスのアプリケーションワークフロー Q1: ユーザーID をもとに動画のコメントを 投稿順(新しいものを先) に取得 Q2: ビデオID をもとにユーザーからのコメントを 投稿順(新しいものを先) に取得
  20. 20. なぜクエリを知ることが重要? - クエリがスキーマデザインを決める - クエリの変更はスキーマの変更を伴う可能性が高い - Apache Cassandra™が得意なアクセスパターンに落とす - 単一パーティションへのクエリー ◎ - 少数のパーティションへのクエリー 〇 - テーブルスキャン × - 複数テーブルへのアクセス × © DataStax, All Rights Reserved.20
  21. 21. 非正規化 - 非正規化 - データをネストする - クラスタリングカラム - ユーザー定義型 - コレクション型 - データを重複して持つ © DataStax, All Rights Reserved.21
  22. 22. 非正規化 - クラスタリングカラム - パーティションキーが親のエンティティを識別 - クラスタリングカラムの値が子のエンティティを識別 - クラスタリングカラムを増やすことで多階層のネストを実現 © DataStax, All Rights Reserved.22
  23. 23. 非正規化 - データを重複して持つ - クライアントサイドJOINよりも重複して持つほうがスケールする © DataStax, All Rights Reserved.23
  24. 24. 概念データ モデル アプリケー ションワー クフロー マッピング 論理データ モデル 最適化 物理データ モデル 論理データモデルの成果物 © DataStax, All Rights Reserved.24 ERDとクエリに マッピングルールとパターンを適用 論理データモデリングの成果物として Chebotkoダイアグラムを作成
  25. 25. Chebotkoダイアグラム © DataStax, All Rights Reserved.25
  26. 26. Chebotkoダイアグラム © DataStax, All Rights Reserved.26
  27. 27. Chebotkoダイアグラム © DataStax, All Rights Reserved.27
  28. 28. Chebotkoダイアグラム © DataStax, All Rights Reserved.28
  29. 29. Chebotkoダイアグラム © DataStax, All Rights Reserved.29
  30. 30. コメント機能のChebotkoダイアグラム © DataStax, All Rights Reserved.30 Q2Q1 Q1: ユーザーID をもとに動画のコメントを 投稿順(新しいものを先) に取得 Q2: ビデオID をもとにユーザーからのコメントを 投稿順(新しいものを先) に取得 comments_by_user comments_by_video userId commentedAt commentId videoId comment videoId commentedAt commentId userId comment K C↑ C K C↑ C
  31. 31. コメント機能のChebotkoダイアグラム TimeUUID - Apache Cassandra のデータ型の一つ - UUID version 1 - IDの中にタイムスタンプを持つ → ソート可能 © DataStax, All Rights Reserved.31
  32. 32. コメント機能のChebotkoダイアグラム © DataStax, All Rights Reserved.32 Q2Q1 Q1: ユーザーID をもとに動画のコメントを 投稿順(新しいものを先) に取得 Q2: ビデオID をもとにユーザーからのコメントを 投稿順(新しいものを先) に取得 comments_by_user comments_by_video userId commentId videoId comment videoId commentId userId comment K C↑ K C↑
  33. 33. コメント機能のデータモデリング CQL DDL © DataStax, All Rights Reserved.33 CREATE TABLE comments_by_video ( videoid uuid, commentid timeuuid, userid uuid, comment text, PRIMARY KEY (videoid, commentid) ) WITH CLUSTERING ORDER BY (commentid DESC); CREATE TABLE comments_by_user ( userid uuid, commentid timeuuid, videoid uuid, comment text, PRIMARY KEY (userid, commentid) ) WITH CLUSTERING ORDER BY (commentid DESC); Q1: SELECT commentid, videoid, comment FROM comments_by_user WHERE userid = ? Q2: SELECT commentid, userid, comment FROM comments_by_video WHERE videoid = ?
  34. 34. アプリケーションの実装 © DataStax, All Rights Reserved.34
  35. 35. アプリケーションの実装 - DataStaxドライバーのセットアップ - Apache Cassandra用 - DataStax Java Driver - https://github.com/datastax/java-driver - APLv2 - API: Cluster / Session - DataStax Enterprise用 - DataStax Enterprise Java Driver - https://github.com/datastax/java-driver-dse - ライセンスは独自 - API: DseCluster / DseSession © DataStax, All Rights Reserved.35
  36. 36. アプリケーションの実装 - Apache Cassandra / DataStax Enterprise への接続 © DataStax, All Rights Reserved.36 Builder clusterConfig = new Builder(); clusterConfig.addContactPoints(cassandraHosts) .withPort(cassandraPort) .withClusterName(CLUSTER_NAME); … DseCluster dseCluster = clusterConfig.build(); return dseCluster.connect(); // DseSessionオブジェクトを返す
  37. 37. アプリケーションの実装 - コメントを登録する - コメントが登録されるとふたつのテーブルに登録しなければならない - バッチ機能を利用してINSERT © DataStax, All Rights Reserved.37 PreparedStatement commentsByUserPrepared = dseSession.prepare( "INSERT INTO killrvideo.comments_by_user (userid, commentid, comment, videoid) VALUES (?, ?, ?, ?)" ).setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM); … BoundStatement bs1 = commentsByUserPrepared.bind(userId, commentId, comment, videoId); BoundStatement bs2 = commentsByVideoPrepared.bind(videoId, commentId, comment, userId); … final BatchStatement batchStatement = new BatchStatement(BatchStatement.Type.LOGGED); batchStatement.add(bs1); batchStatement.add(bs2); batchStatement.setDefaultTimestamp(now.getTime()); FutureUtils.buildCompletableFuture(dseSession.executeAsync(batchStatement)) …
  38. 38. アプリケーションの実装 - コメントを取得する - ステートメントの組み立て © DataStax, All Rights Reserved.38 PreparedStatement getVideoComments_startingPointPrepared = dseSession.prepare( QueryBuilder.select() .column("video_id") .column("comment_id") .column("user_id") .column("comment") .fcall("toTimestamp", QueryBuilder.column("comment_id")).as("comment_timestamp") .from("killrvideo", "comments_by_video") .where(QueryBuilder.eq("video_id", QueryBuilder.bindMarker())) .and(QueryBuilder.lte("comment_id", QueryBuilder.bindMarker())) ).setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM);
  39. 39. アプリケーションの実装 - コメントを取得する - 取得件数の指定とページング © DataStax, All Rights Reserved.39 final Optional<String> pagingState = Optional.ofNullable(request.getPagingState()) .filter(StringUtils::isNotBlank); … statement = getUserComments_startingPointPrepared.bind() .setUUID("userid", fromString(userId.getValue())) .setUUID("commentid", fromString(startingCommentId.getValue())); … statement.setFetchSize(request.getPageSize()); pagingState.ifPresent( x -> statement.setPagingState(PagingState.fromString(x))); … Optional.ofNullable(commentResult.getExecutionInfo().getPagingState()) .map(PagingState::toString) .ifPresent(builder::setPagingState);
  40. 40. アプリケーションの実装 - コメントを取得する - クエリの実行結果の取得 © DataStax, All Rights Reserved.40 FutureUtils.buildCompletableFuture(dseSession.executeAsync(statement)) .handle((commentResult, ex) -> { … int remaining = commentResult.getAvailableWithoutFetching(); for (Row row : commentResult) { CommentsByUser commentByUser = new CommentsByUser( row.getUUID("userid"), row.getUUID("commentid"), row.getUUID("videoid"), row.getString("comment") ); commentByUser.setDateOfComment( row.getTimestamp("comment_timestamp")); builder.addComments(commentByUser.toUserComment()); if (--remaining == 0) break; } …
  41. 41. アプリケーションの実装 - その他の実装サンプル - オブジェクトマッパーの利用 - DSEの機能を利用して - グラフ形式にデータを格納して、リアルタイムレコメンデーションのクエリを実行 - 全文検索インデックスを利用した検索 © DataStax, All Rights Reserved.41
  42. 42. さらに詳しく © DataStax, All Rights Reserved.42
  43. 43. もっと詳しく! - ダウンロードとフリーのオンライントレーニング - 開発用途に無償利用可能 - DS201: Apache Cassandra入門 - DS220: データモデリング - https://academy.datastax.com/ © DataStax, All Rights Reserved.43

×