More Related Content Similar to 高負荷に耐えうるWebApplication Serverの作り方 (20) More from GMO-Z.com Vietnam Lab Center (20) 高負荷に耐えうるWebApplication Serverの作り方2. Xin chào!
Toi ten la Ishiyama Yuta.
GMO Internet inc.
次世代システム研究室
(Innovation and Technology System Office)
アシスタントマネージャー(Asistant Manager)
シニアアーキテクト(Senior Architect)
Engineer歴 20年
好き DB / Elixir-lang
自己紹介
2
3. Goal
高負荷に耐えうる WebApplication の Architecture
を設計する際に
・どこで対策するか
・どのように作るか
をご紹介します。
Programing codeではなくinfraよりの説明になり
ます。高負荷対策は多数ありますが一例とおぼえ
ておいていただくことをGoalとしています。
3
36. ◆データ毎の水平分割例
[ルール] user_id の 偶数(even) / 奇数(odd) などで分ける
DB ~Horizontal sharding~
slave/
master
slave backup
36
user_id even
slave/
master
slave backup
user_id odd
API PHP-FPM
Programで接続先DB
を使い分ける
37. ◆C2での水平分割例
C2ではDB Serverを2セット、DB schemaを8分割しています
[ルール] user_id % 8 で8分割(剰余算 mod)
DB負荷が上がったら最大8台のDB Serverへ分割可能です
※mod 128にすれば128台へ分割可能ですが管理が大変なのでほどほどに...
DB ~Horizontal sharding/c2~
slave/
master
slave backup
37
db
00,02,04,06
を保存 slave/
master
slave backup
db
01,03,05,07
を保存
API PHP-FPM
Programでルールに合わせて接続先DB
を使い分ける
mod 0,2,4,6ならば server1mへ
mod 1,3,5,7ならば server2mへ
00 02
04 06
00 02
04 06
01 03
05 07
01 03
05 07
[db server1m]
[db server1s] [db server2s]
[db server2m]
39. CREATE TABLE文
CREATE TABLE `log_training`(
`id` bigint unsigned auto_increment NOT NULL COMMENT '管理用ID'
,`user_id` int unsigned NOT NULL COMMENT 'ユーザーID'
,`mst_training_id` int unsigned NOT NULL COMMENT '特訓ID'
,`type` int unsigned NOT NULL COMMENT '種別(0:消費、1:付与、2:売却)'
,`amount` int NOT NULL COMMENT '増減量'
,`count` int unsigned NOT NULL COMMENT '個数'
,`created` datetime NOT NULL COMMENT '登録日時'
,PRIMARY KEY(`id`, `user_id`)
,KEY log_training_idx1(`user_id`)
,KEY log_training_idx2(`mst_training_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='特訓ログ'
PARTITION BY HASH(MOD(`user_id`, 100)) PARTITIONS 100;
※ user_idを100で割った余りでpartition100個を入れ分けている
※ 主キーにpartition ルールで使っているuser_idカラムを含めている
DB ~table partitioning~
39
40. ◆ Table partitioningのイメージ図
Table log_training
DB ~table partitioning~
40
1つのTable
保存領域がわか
れている
クエリのWHERE句にuser_idを指定して検索すると
該当の領域のみSeekする
[ルール] user_id % 100
・mod 0 -> 00の領域へ保存
・mod 1 -> 01の領域へ保存
・mod 99-> 99の領域へ保存
00
X
[Table log_training]
01 03 04 05 06 99
保存領域
47. Nginx ~説明~
Nginxは http daemon であり Non blocking I/O
と async I/O により大量のアクセスに対応する
ことが可能
URLによる L7 Load balancing が可能
LuaスクリプトやC言語で独自の判定処理を実装
出来て複雑な処理も可能
47
57. ◆ Backupは mysql dir毎コピーを取る方法がおす
すめ
・tarコマンド等で /var/lib/mysql 毎バックアップする
・/var/lib/mysql/master.infoファイルにreplication設定や
binlog positionが記入されているため、masterDBにbinlogファ
イルが残っていればバックアップから最新状態まで復旧可能
DB ~気をつける事 2/2~
57
60. c2でのmy.cnf設定(Ansible template)
character_set_server: utf8mb4
max_connections: 10000
max_connect_errors: 50
transaction-isolation: READ-COMMITTED
# innodb
innodb_buffer_pool_size: 64G
innodb_buffer_pool_instances: 16
innodb_flush_method: O_DIRECT
innodb_flush_log_at_trx_commit: 1
innodb_file_per_table: 1
innodb_data_file_path: ibdata1:10M:autoextend
innodb_file_format: Barracuda
open_files_limit: 163840
innodb_open_files: 128000
DB ~my.cnf 1/3~
60
61. # Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size: 2G
innodb_log_buffer_size: 64M
innodb_support_xa: 1
innodb_lock_wait_timeout: 5
# io threads 並列化可能な状況ならば max64 以内で設定
innodb_write_io_threads: 16
innodb_read_io_threads: 16
innodb_thread_concurrency: 0
# fusion-io/SSD
innodb_io_capacity_max: 30000
innodb_io_capacity: 20000
# memory
sort_buffer_size: 2M
join_buffer_size: 2M
read_buffer_size: 1M
max_allowed_packet: 4M
DB ~my.cnf 2/3~
61
62. # replication
server_id: "{{ ansible_all_ipv4_addresses[0].split('.')[3] }}"
log_slave_updates: ON
# binlog
log_bin: mysql-bin
binlog_format: MIXED
expire_logs_days: 180
max_binlog_size: 500MB
DB ~my.cnf 3/3~
62
65. 重要な Linux kernel設定
net.core.somaxconn=65535
TCP接続数 最大Port数に設定するのがおすすめ
net.ipv4.ip_local_port_range=10000 65535
Ephemeral portを設定、上記だとdefault 28000のところを55000使えるように
なる
net.ipv4.tcp_fin_timeout=5
TCPセッションがFIN-WAIT2からTIME_WAITへ変化する時間
net.ipv4.tcp_tw_reuse=1
TIME_WAIT状態のportの再利用を行う(接続先IP/portが同じサーバーの場合に
再利用可能)
=>上記設定で同時通信数の最大化やport枯渇対策が可能
Kernel設定 ~/etc/sysctl.conf 1/3~
65