2024.10.01
【勉強】ミドルウェア・アプリケーションのEOL・EOSLについて学んでみた
2018.11.20
プログラミングSpringでMaster/Slave構成のMySQLに接続する(with Kotlin)
こんにちは、MTです。
今回は、Master/Slave構成のMySQLに接続する方法についてです。
(具体的には、クエリの発行先をMasterとSlaveで切り替える方法について)
■言語
・Kotlin 1.3.0
■アプリケーション
・SpringBoot 2.1.0
・mysql-connector-java 5.1.45
■MySQL 5.6
・Masterのホスト : localhost:3306
・Slave のホスト : localhost:3307
なお、MySQL自体のレプリケーション設定については触れていません。
通常はurlに指定するのは jdbc:mysql://
スキームですが、Master/Slave構成の場合は jdbc:mysql:replication://
スキームを使用します。
そして jdbc:mysql:replication://
スキームに続けて、Masterのホストアドレス、Slaveのホストアドレスの順にカンマ区切りで記載していきます。
spring: datasource: driver-class-name: "com.mysql.jdbc.Driver" url: "jdbc:mysql:replication://localhost:3306,localhost:3307/dev" username: "dev" password: "password"
こんな感じ。(末尾の /dev はデータベース名。) Slaveの指定は複数でもOKです。
宣言的トランザクションを利用している場合、readOnly
オプションに true
を指定すれば Slave に向きます。
@Transactional(readOnly = true) fun findAllBySlave(): List<User> = this.userRepository.findAll()
明示的トランザクションを利用する場合は、 java.sql.Connection
インタンスを取得し、setReadOnly
メソッドに true
を設定してください。
事前に以下の user テーブルを作成し、MasterとSlaveで異なるデータを登録しておきます。
CREATE TABLE IF NOT EXISTS user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Master側 INSERT INTO user (name) VALUES ("user1"), ("user2"),( "user3");
-- Slave側 INSERT INTO user (name) VALUES ("user4"), ("user5"),( "user6");
次にデータを取得するサービス層で、宣言的トランザクションを利用して、読み取り専用とするかを定義しておきます。
@Service class UserService(private val userRepository: UserRepository) { @Transactional(readOnly = false) fun findAllByMaster(): List<User> = this.userRepository.findAll() @Transactional(readOnly = true) fun findAllBySlave(): List<User> = this.userRepository.findAll() }
ユーザ情報を取得するためのエンドポイントは以下のようにしました。
・/master
: Master側に登録されたユーザ情報を取得する。
・/slave
: Slave側に登録されたユーザ情報を取得する。
ではアクセスしてみます。
$ curl localhost:8080/master [{"id":1,"name":"user1"},{"id":2,"name":"user2"},{"id":3,"name":"user3"}] $ curl localhost:8080/slave [{"id":1,"name":"user4"},{"id":2,"name":"user5"},{"id":3,"name":"user6"}]
ちゃんと向き先が変わってますね。
spring: datasource: driver-class-name: "com.mysql.jdbc.Driver" url: "jdbc:mysql:replication://localhost:3306,localhost:3307/dev" username: "dev" password: "password"
@RestController @SpringBootApplication class MysqlReplicationSandboxApplication constructor(private val service: UserService) { @RequestMapping("master") fun getByMaster(): List<User> = this.service.findAllByMaster() @RequestMapping("slave") fun getBySlave(): List<User> = this.service.findAllBySlave() companion object { @JvmStatic fun main(args: Array<String>) { SpringApplication.run(MysqlReplicationSandboxApplication::class.java, *args) } } } @Entity data class User ( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long, val name: String ): Serializable @Service class UserService(private val userRepository: UserRepository) { @Transactional(readOnly = false) fun findAllByMaster(): List<User> = this.userRepository.findAll() @Transactional(readOnly = true) fun findAllBySlave(): List<User> = this.userRepository.findAll() } @Repository interface UserRepository : JpaRepository<User, Long>
version: '3.1' services: db1: image: mysql:5.6 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD : "password" MYSQL_DATABASE: "dev" MYSQL_USER: "dev" MYSQL_PASSWORD: "password" volumes: - ./mysql/init_master/:/docker-entrypoint-initdb.d db2: image: mysql:5.6 ports: - "3307:3306" environment: MYSQL_ROOT_PASSWORD : "password" MYSQL_DATABASE: "dev" MYSQL_USER: "dev" MYSQL_PASSWORD: "password" volumes: - ./mysql/init_slave/:/docker-entrypoint-initdb.d
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
タグ検索