SlideShare une entreprise Scribd logo
1  sur  51
Télécharger pour lire hors ligne
1
ソーシャルゲーム案件における
DB 分割の PHP 実装
~とにかく分割ですよ。 10 回じゃ足りない。 20 回くらい分割。~
株式会社インフィニットループ
佐々木 亨基
自己紹介
・佐々木 亨基
・ゆきこ yukicon
・ Twitter:@yukiconEx
・株式会社インフィニットループ所属
・札幌 MySQL 勉強会代表
・ PHP 歴は 4 年くらい
・現在仕事では PHP オンリー
・いい加減な人間なので PHP の緩さは好き
インフィニットループについて
・北海道札幌市にあるシステム開発会社
 約 90 名(契約スタッフ・アルバイト含む)で活動中
 社長も含め、ほぼ全員がエンジニア
・主な開発実績(主にサーバサイドを担当)
 ブラウザ三国志 (2009)
 英雄クエスト (2010)
  Lord of Knights(2012)
 フォトバトラー (2012)
  Vim 検定 (2012)
  PHP 検定 (2013)
 その他いろいろ
お題目
■ はじめに
・ DB 分割とは
・どうして DB 分割なんかするの?
・ユーザ単位による水平分割
・ DB 分割のデメリット
お題目
■ 実装のお話
・クラス設計
・使用例
・エイリアス
・水平分割
・水平分割された DB への問い合わせ
・トランザクション
・トランザクションの開始
・コミット
・まとめ
DB 分割とは
分割していない DB
A テーブル
B テーブル
C テーブル
D テーブル
E テーブル
F テーブル
DB 分割とは
分割した DB
A テーブル
B テーブル
E テーブル
F テーブル
E テーブル
F テーブル
E テーブル
F テーブル …
垂直分割
( テーブル単位での分割 )
水平分割
( 同テーブルの ID 単位による分割 )
C テーブル
D テーブル
DB 分割とは
更にそれぞれがマスタスレーブ構成を取る
Master
Master
…
垂直分割
( テーブル単位での分割 )
水平分割
( 同テーブルの ID 単位による分割 )
Slave Slave Slave
Master
Slave Slave Slave
Slave Slave Slave
Master
Slave Slave Slave
Master
Slave Slave Slave
どうして DB 分割なんかするの?
■ 要件
数万~十数万の同時接続数に耐えられるシステム
■ 案件の特徴
ソーシャルゲーム案件の規模は予測が難しい
突然跳ねる事もあり、正確な規模が見積もれない
どうして DB 分割なんかするの?
・同時接続数万という要求は高い
・さらに予想を上回る可能性もある
・しかしその実さっぱり流行らない可能性もある
・スモールスタート可能
・かつ困った時にサーバ追加で解決できる構成
つまり
スケールアウト可能なシステム構成
どうして DB 分割なんかするの?
Web サーバは単純なサーバ追加で対応可能
しかし DB は簡単にはいかない
・・・ ×nWeb Web Web Web
DB × ?
どうして DB 分割なんかするの?
DB のスケールアウトと言えばマスタスレーブ構成
Master
Slave Slave Slave ・・・ ×n
SELECT
UPDATE
SELECT SELECT
どうして DB 分割なんかするの?
しかしマスタスレーブ構成のマスタサーバは 1 台
マスタサーバの更新性能がネックとなり
いずれ限界が来る
Master
Slave Slave Slave ・・・ ×n
SELECT
UPDATE
SELECT SELECT
どうして DB 分割なんかするの?
マスタ 1 台で数万の同時接続数を捌くのは不可能
要件的にマスタスレーブ構成では破綻する
どうして DB 分割なんかするの?
ではどうする?
・ Fusion-io のような超高速ストレージを使う?
 →用意できるとは限らない
 →導入しても解決しなかった場合に詰む
・ MySQL Cluster を使う?
 →まだ枯れていない技術という印象
 →制約も多く、導入は怖い
どうして DB 分割なんかするの?
マスタスレーブのセットを増やそう !
       |
   \   __   /
    _ (m) _ピコーン
       | ミ |
    /  ` ´   \
      ('A`)
     ノヽノヽ
       くく
ユーザ単位による DB 分割
ユーザ数が増えたなら UserDB を追加
Global が苦しくなったら更に垂直分割をする事で
スケールアウト可能
User1 User2 User3 …
水平分割された UserDB
ユーザに紐付くデータを一定のルールで振り分けて格納
Global
GlobalDB
ユーザに紐付かない共通のデータを格納
DB 分割のデメリット
■ 設計でカバーする
・ DB 間を跨いだ JOIN ができない
→ 冗長なデータの持ち方をしてしまう
→ マスタデータは全 DB に持つなどして対策
・水平分割すればするほどパフォーマンスが下がる
 ※とにかく分割とかいうタイトルになってますが
  あんまり分割しちゃダメです、最低限にしましょう
DB 分割のデメリット
■ できるだけライブラリ側で吸収する
・水平分割された DB の串刺し検索が大変
→ ユーザ一覧を持ってくるのですら一苦労
・複数 DB のトランザクション管理が煩雑
ここからは実装のお話
クラス設計
3 つのクラスから成っている
・ DatabaseAccess
 全 DB 、トランザクションを統括するクラス
・ DatabaseAccessNode
 単一 DB にアクセスするクラス
 マスタスレーブの切り替えも行う
 分割なしならこのクラスのみで完結
・ DatabaseAccessMultiNode
 水平分割された DB にまとめてアクセスするクラス
クラス設計
図にすると
Master
Master
…
DatabaseAccess
Slave Slave Slave
Master
Slave Slave Slave
Slave Slave Slave
Master
Slave Slave Slave
Master
Slave Slave Slave
DatabaseAccessNode
DatabaseAccessMultiNode
使用例
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->getDBAN('global')->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->getDBAN('user', $user_id)->select('user_tbl');
// 複数の対象ユーザ DB から SELECT
$dban_arr = $dba->getDBANArr('user', $user_id_arr);
$dbam = new DatabaseAccessMultiNode($dban_arr);
$dbam->select('user_tbl');
使用例
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->getDBAN('global')->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->getDBAN('user', $user_id)->select('user_tbl');
// 複数の対象ユーザ DB から SELECT
$dban_arr = $dba->getDBANArr('user', $user_id_arr);
$dbam = new DatabaseAccessMultiNode($dban_arr);
$dbam->select('user_tbl');
なんか難しい!
エイリアス
エイリアスをつくって抽象化
class DatabaseAccess
{
function gb()
{
// global の DatabaseAccessNode オブジェクトを返す
return $this->getDBAN('global');
}
function user($user_id)
{
// user の DatabaseAccessNode オブジェクトを返す
return $this->getDBAN('user', $user_id);
}
:
:
エイリアス
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->gb()->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->user($user_id)->select('user_tbl');
// 複数のユーザ DB から SELECT
$dba->user_multi($user_id_arr)->select('user_tbl');
だいぶすっきり
エイリアス
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->gb()->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->user($user_id)->select('user_tbl');
// 複数のユーザ DB から SELECT
$dba->user_multi($user_id_arr)->select('user_tbl');
// 全ユーザ DB から SELECT
$dba->user_all()->select('user_tbl');
全ユーザ DB 用のエイリアスも用意すると便利
水平分割
ID とサーバ ID をマッピングするテーブルを
グローバル DB に作成して管理
CREATE TABLE `id_partition_tbl` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`server_id` tinyint(4) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `server_id` (`id`,`server_id`)
)
id server_id
1000 1
1001 2
1002 3
水平分割
ID の発行 ( 仮に server_id を 1 で指定 )
INSERT INTO id_partition_tbl (server_id) VALUE (1);
SELECT LAST_INSERT_ID();
 ↓
分割ルールに従ってサーバの割り当て
 ↓
テーブルへの登録
UPDATE id_partition_tbl SET server_id = 3 WHERE id = 1000;
水平分割
分割ルール
・テーブルによる管理
必ずテーブルを参照する必要がある
server_id をキャッシュするなどの工夫が必要
登録数の少ないサーバに振り分け
各サーバに重みをつけて振り分け
既存データを意図通りに再配置
など柔軟な対応が可能
$server_id = getServerId('id_partition_tbl', $id);
水平分割
分割ルール
・剰余やハッシュによる振り分け
均等にバランシングされる
サーバ追加時に既存データの再配置が必要
$server_id = ($id % $server_cnt) + 1;
水平分割
分割ルール
・範囲による振り分け
ある程度意図を持ってバランシングできる
既存データに手をいれずサーバ追加が可能
ただし小回りは効かない
foreach ($range_arr as $range) {
if ($range['min'] <= $id and $id <= $range_info['max']) {
$server_id = $range['server_id'];
break;
}
}
水平分割された DB への問い合わせ
DatabaseAccessMultiNode クラスにより実現
複数 DB に同じ SQL を投げ、結果をマージ
使用者は複数 DB への問い合わせである事を意識
せず、単一 DB を扱うのと同様に記述する事がで
きる
// 単一 DB への問い合わせ
$dba->user($user_id)->select('user_tbl');
$dba->user($user_id)->update('user_tbl');
// 複数 DB への問い合わせ
$dba->user_multi($user_id_arr)->select('user_tbl');
$dba->user_multi($user_id_arr)->update('user_tbl');
水平分割された DB への問い合わせ
__call と call_user_func_array によって実装
DatabaseAccessNode クラスに単一 DB へ問い合
わせる処理を追加すると、
DatabaseAccessMultiNode クラスを経由して複
数 DB に問い合わせもする事ができる
class DatabaseAccessMultiNode
{
function __call($func_name, $args = array())
{
// 各 DB に対して実行
foreach ($this->dban_arr as $key => $dban) {
$tmp_data_arr[] =
call_user_func_array(array($dban, $func_name), $args);
}
水平分割された DB への問い合わせ
レスポンスは型によって処理を振り分ける
$tmp_data = reset($tmp_data_arr);
if (is_numeric($tmp_data)) {
// 数値の場合は和を返す
$sum = 0;
foreach ($tmp_data_arr as $tmp_data) {
$sum += $tmp_data;
}
return $sum;
} else if (is_array($tmp_data)) {
// 配列の場合はマージして返す
$data = array();
foreach ($tmp_data_arr as $tmp_data) {
$data = array_merge($data, $tmp_data);
}
return $data;
:
:
水平分割された DB への問い合わせ
user_id をキーにした場合
UPDATE は対象レコードが存在しないため問題無いが
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
水平分割された DB への問い合わせ
INSERT は気をつける必要がある
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
水平分割された DB への問い合わせ
INSERT は気をつける必要がある
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
不要なレコードまで INSERT されてしまう
水平分割された DB への問い合わせ
__call による実装は、あくまでも全 DB に同じ
クエリを投げているだけ
レスポンスも型によって機械的に対応している
INSERT のようにそれでは問題がある場合は、
専用メソッドを立てて対応する
トランザクション
トランザクションは DB 単位でかかるため
管理に気を使わなくてはいけない
// 対象のユーザ DB にトランザクション開始
$dba->beginTransactionToUser($user_id);
// この更新はグローバル DB への更新のため
// トランザクションの対象とならない
$dba->gb()->update();
XA トランザクション…
うっ…頭が…
( 分離レベルが SERIALIZABLE に限られる、
 挙動が怪しいという事で、ミドルウェアに頼らず
 アプリによる実装としました )
トランザクションの開始
複数 DB へのトランザクション開始方法は 2 通り
・最初にまとめて開始してしまう
・必要になった時点で開始する
トランザクションが必要な事がわかりきっている場合は最
初にまとめてしまう方が管理が楽かつ簡単
どれか 1 つでもトランザクションがかかっていれば他の DB
も更新処理時に自動でトランザクション状態となるオート
モードも用意したが、管理できなくなる懸念があったため
使っていない
トランザクションの開始
■ 最初にまとめて開始してしまう場合
トランザクションは短い方が良い
コネクションのコストによって無用にトランザクションが
長くならないようにマスタサーバへのコネクションを行
なってからまとめてトランザクションを開始する
// 対象の DB をマスタに接続
$dba->gb()->useMaster();
$dba->user($user_id)->useMaster();
// マスタに接続した DB を一斉にトランザクション開始
$dba->myBeginTransactionToConnectionMaster();
Global User
コネクション
BEGIN
コネクション
BEGIN
Global User
コネクション
コネクション
BEGIN
BEGIN
トランザクションの開始
■ 必要になった時点で開始する場合
ある DB に対してトランザクションをかけるが、
ある DB に対しては 10 回に 1 回くらいしかトランザクショ
ンが必要が無い処理の場合、必要になった時にトランザク
ションを開始する
別々のユーザ ID が対象になった際に両方のユーザ ID が同
じ DB に所属している場合など、既にトランザクションが開
始されている事もある
// 対象のユーザ DB にトランザクション開始
$dba->beginTransactionToUser($user_id);
// たまにしかここに来ないので、ここでトランザクション開始
// 既にトランザクション開始されているならスルーする
If ($dba->user($other_user_id)->isTransaction()) {
// 同じ DB の場合はここにはこない
$dba->beginTransactionToUser($other_user_id);
}
コミット
各 DB に対してバラバラのタイミングでコミットを行うとつ
くりが複雑になり、データ不整合となるバグを引き起こす
可能性が高くなる
悪い例
// グローバル DB をアップデート
$dba->gb()->update();
// グローバル DB をコミット
$dba->commitToGlobal();
// ユーザ DB をアップデート
$dba->user($user_id)->update();
// ユーザ DB をコミット
$dba->commitToUser($user_id);
ここでエラーが起こるとユーザ DB のみ更新されず
データ不整合状態となる
Global User
UPDATE
COMMIT
UPDATE
COMMIT
コミット
コミットは必ず処理の最後にまとめて行うようにする
処理の順番によるデータ不整合に気を配る必要が無くなり
コーディングの難易度も下がる
// グローバル DB をアップデート
$dba->gb()->update();
// ユーザ DB をアップデート
$dba->user($user_id)->update();
// まとめてコミット
$dba->allCommit();
Global User
UPDATE
UPDATE
COMMIT
COMMIT
コミット
まとめてコミットと言っても順番にコミットするだけ
いわゆる 2 相コミットではないため、一部がコミットされ
てしまうと全体のロールバックは不可能
やはり途中でエラーとなった場合はデータ不整合となる
$commited_arr = array();
foreach ($dban_arr as $dban) {
$dban->commit();
$commited_arr[] = $dban->database_name;
}
コミット
途中でコミットがエラーとなった場合は、どの DB がコミッ
トされ、どの DB がコミットされていないのかをログに残す
} catch (Exception $e) {
if (0 < count($commited_arr)) {
// 1 度以上コミットしたということはデータ不整合
$uncommited_arr = array();
foreach ($dban_arr as $dban) {
if ($dban->isTransaction()) {
// トランザクション中なら配列に含める
$uncommited_arr[] = $dban->database_name;
}
}
// エラーとなった DB 情報のログを残す
logging(sprintf('commit error commited[%s]
uncommited[%s]', implode(',', $commited_arr),
implode(',', $uncommited_arr)));
}
}
コミット
ログを頼りに手で対応する事になってしまうが
実際データ不整合はほとんど起こらず
1 年で 1 回や 2 回という低い頻度のため
ログによる対応で問題となった事はない
まとめ
・エイリアスを用意
・複数 DB を束ねて管理するクラスを用意
抽象化は重要
抽象化する事で経験の浅いエンジニアでも扱える
・分割ルールは設計段階で破綻の無いように決めておく
必要であれば独自のルールによる振り分けを実装する
・トランザクションの管理もできるだけ簡単にする
・特にコミットはデータ不整合の起こりやすいポイント
・ 2 相コミットではない
・一部コミットされると全体ロールバックは不可
・データ不整合はコミット失敗のログを残す事で対応する
DB 分割意外となんとかなる
でも気をつけるところはちゃんと気をつけないとダメ
求人募集
インフィニットループでは、エンジニアを募集しています
・社長も含めほぼ全員がプログラマで技術者に優しい環境
・勤務地は北海道札幌市、他社出向などは無し
・おいしい食べ物、自然いっぱい、花粉少ない、涼しい
・短い通勤時間、徒歩や自転車で通勤が可能
・ U ターン、 I ターン大歓迎
・ PHP 開発エンジニア
・スマホ開発エンジニア
・ MySQL エンジニア
・インフラエンジニア
ご清聴ありがとうございました

Contenu connexe

Tendances

文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)
Hiroshi Tokumaru
 

Tendances (20)

マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
WebSocket / WebRTCの技術紹介
WebSocket / WebRTCの技術紹介WebSocket / WebRTCの技術紹介
WebSocket / WebRTCの技術紹介
 
nginx入門
nginx入門nginx入門
nginx入門
 
PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発
PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発
PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
 
webエンジニアのためのはじめてのredis
webエンジニアのためのはじめてのrediswebエンジニアのためのはじめてのredis
webエンジニアのためのはじめてのredis
 
Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版
 
初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
Docker Tokyo
Docker TokyoDocker Tokyo
Docker Tokyo
 
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみようドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
 
文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)
 
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajpAt least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルド
 

Similaire à ソーシャルゲーム案件におけるDB分割のPHP実装

月間10億pvを支えるmongo db
月間10億pvを支えるmongo db月間10億pvを支えるmongo db
月間10億pvを支えるmongo db
Yuji Isobe
 
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
Masahiro Nagano
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
Naoyuki Yamada
 
Databasedesignforsocialgames 110115195940-phpapp02
Databasedesignforsocialgames 110115195940-phpapp02Databasedesignforsocialgames 110115195940-phpapp02
Databasedesignforsocialgames 110115195940-phpapp02
hideki hasegawa
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
Hidekazu Ishikawa
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介
Kevin Toyoda
 
My sql casual_in_fukuoka_vol1
My sql casual_in_fukuoka_vol1My sql casual_in_fukuoka_vol1
My sql casual_in_fukuoka_vol1
Makoto Haruyama
 

Similaire à ソーシャルゲーム案件におけるDB分割のPHP実装 (20)

Webで役立つRDBの使い方
Webで役立つRDBの使い方Webで役立つRDBの使い方
Webで役立つRDBの使い方
 
月間10億pvを支えるmongo db
月間10億pvを支えるmongo db月間10億pvを支えるmongo db
月間10億pvを支えるmongo db
 
進化したのはサーバだけじゃない!〜DBA の毎日をもっと豊かにするユーティリティのすすめ〜
進化したのはサーバだけじゃない!〜DBA の毎日をもっと豊かにするユーティリティのすすめ〜進化したのはサーバだけじゃない!〜DBA の毎日をもっと豊かにするユーティリティのすすめ〜
進化したのはサーバだけじゃない!〜DBA の毎日をもっと豊かにするユーティリティのすすめ〜
 
Oracle Data Guard による高可用性
Oracle Data Guard による高可用性Oracle Data Guard による高可用性
Oracle Data Guard による高可用性
 
Easy caching and logging package using annotation in Python
Easy caching and logging package using annotation in PythonEasy caching and logging package using annotation in Python
Easy caching and logging package using annotation in Python
 
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
Teclab3
Teclab3Teclab3
Teclab3
 
Databasedesignforsocialgames 110115195940-phpapp02
Databasedesignforsocialgames 110115195940-phpapp02Databasedesignforsocialgames 110115195940-phpapp02
Databasedesignforsocialgames 110115195940-phpapp02
 
Phpcon2015
Phpcon2015Phpcon2015
Phpcon2015
 
Zend Frameworkで始める携帯サイト
Zend Frameworkで始める携帯サイトZend Frameworkで始める携帯サイト
Zend Frameworkで始める携帯サイト
 
PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
 
PHPからJavaへ乗り換えた。そんな昔話をしよう
PHPからJavaへ乗り換えた。そんな昔話をしようPHPからJavaへ乗り換えた。そんな昔話をしよう
PHPからJavaへ乗り換えた。そんな昔話をしよう
 
Rで触れる日本経済~RでVAR編~
Rで触れる日本経済~RでVAR編~Rで触れる日本経済~RでVAR編~
Rで触れる日本経済~RでVAR編~
 
Develop Web Application with Node.js + Express
Develop Web Application with Node.js + ExpressDevelop Web Application with Node.js + Express
Develop Web Application with Node.js + Express
 
シラサギハンズオン 東京
シラサギハンズオン 東京シラサギハンズオン 東京
シラサギハンズオン 東京
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介
 
My sql casual_in_fukuoka_vol1
My sql casual_in_fukuoka_vol1My sql casual_in_fukuoka_vol1
My sql casual_in_fukuoka_vol1
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみよう
 

Plus de infinite_loop

Plus de infinite_loop (20)

ChatGPT触ってみた
ChatGPT触ってみたChatGPT触ってみた
ChatGPT触ってみた
 
社内ソフトスキルを考える
社内ソフトスキルを考える社内ソフトスキルを考える
社内ソフトスキルを考える
 
3Dプリンタって いいね
3Dプリンタって いいね3Dプリンタって いいね
3Dプリンタって いいね
 
VRChatでお酒が注げる飲み物アセットの紹介
VRChatでお酒が注げる飲み物アセットの紹介VRChatでお酒が注げる飲み物アセットの紹介
VRChatでお酒が注げる飲み物アセットの紹介
 
アニメーションとスキニングをBurstで独自実装する.pdf
アニメーションとスキニングをBurstで独自実装する.pdfアニメーションとスキニングをBurstで独自実装する.pdf
アニメーションとスキニングをBurstで独自実装する.pdf
 
I ❤ Virtual Machines 仮想環境をより便利に使うツールたち
I ❤ Virtual Machines 仮想環境をより便利に使うツールたちI ❤ Virtual Machines 仮想環境をより便利に使うツールたち
I ❤ Virtual Machines 仮想環境をより便利に使うツールたち
 
500万行のPHPプロジェクトにおけるログ出力の歩み
500万行のPHPプロジェクトにおけるログ出力の歩み500万行のPHPプロジェクトにおけるログ出力の歩み
500万行のPHPプロジェクトにおけるログ出力の歩み
 
ADRという考えを取り入れてみて
ADRという考えを取り入れてみてADRという考えを取り入れてみて
ADRという考えを取り入れてみて
 
リファクタリングで実装が○○分短縮した話
リファクタリングで実装が○○分短縮した話リファクタリングで実装が○○分短縮した話
リファクタリングで実装が○○分短縮した話
 
ゲームのインフラをAwsで実戦tips全て見せます
ゲームのインフラをAwsで実戦tips全て見せますゲームのインフラをAwsで実戦tips全て見せます
ゲームのインフラをAwsで実戦tips全て見せます
 
楽しいVR空間を作る技術と支える技術 #osc19do
楽しいVR空間を作る技術と支える技術 #osc19do楽しいVR空間を作る技術と支える技術 #osc19do
楽しいVR空間を作る技術と支える技術 #osc19do
 
Start rl with_unity_machine_learning_agents
Start rl with_unity_machine_learning_agentsStart rl with_unity_machine_learning_agents
Start rl with_unity_machine_learning_agents
 
UniRx の1歩目
UniRx の1歩目UniRx の1歩目
UniRx の1歩目
 
がんばれ PHP Fiber
がんばれ PHP Fiberがんばれ PHP Fiber
がんばれ PHP Fiber
 
心に残った名前ランキング
心に残った名前ランキング心に残った名前ランキング
心に残った名前ランキング
 
プログラムと名前にまつわる座談会
プログラムと名前にまつわる座談会プログラムと名前にまつわる座談会
プログラムと名前にまつわる座談会
 
名は体を表していますか
名は体を表していますか名は体を表していますか
名は体を表していますか
 
名前の力
名前の力名前の力
名前の力
 
大切な名前[Intro]公開版
大切な名前[Intro]公開版大切な名前[Intro]公開版
大切な名前[Intro]公開版
 
JupyterNotebookとMySQLでゼロからはじめるデータサイエンス
JupyterNotebookとMySQLでゼロからはじめるデータサイエンスJupyterNotebookとMySQLでゼロからはじめるデータサイエンス
JupyterNotebookとMySQLでゼロからはじめるデータサイエンス
 

Dernier

Dernier (12)

LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 

ソーシャルゲーム案件におけるDB分割のPHP実装