DBCharmer를 사용하고 있었는데, 더 이상 업데이트를 안한다고 해서 다른 걸 찾다보니 이거 밖에 없네요 레일즈4에서 사용해야 하는데, DBCharmer는 3.X버전밖에 지원하지 않아요. 그래서 옮길 겸 정리!
물론 Replication(Master/Slave) 외에 Shard도 지원하는데, 그냥 여러 개의 Database를 정의하고 그 중 원하는 걸로 쓰게 하는 형식으로 되어있어요. 즉 키별로 샤드를 나누려면 직접 구현해야할 것 같아요. 그냥 Database를 선택해서 쓸 수 있다 정도로만 되어 있는 것 같네요. 샤드는 잘 안해봐서 잘 모르겠지만 대충 그런 느낌이네요.
일단 나의 정리의 목적은 Replication이니까 이것만-_-
젬 깃허브입니다.
https://github.com/tchandy/octopus
1. Master/Slave DB준비
보통은 시스템팀이 있는 회사라면 다 알아서 해주지만 한 번 해보는 것도 나쁘진 않아요. 이거 보고 따라하세요. 두 번 따라하세요-_-
http://oqlid.blogspot.kr/2013/05/mariadb-masterslave-replication-tutorial.html
2. Rails4 프로젝트 생성.
루비와 레일즈는 셋팅이 되어있다는 가정하에...
rails new ReplicationTest
3. Gemfile에 Octopus 및 필요한 것 추가.
Gemfile
gem 'ar-octopus' gem 'mysql2'
옥토퍼스랑 mysql만 있으면 돼요.
4. database 설정
DBCharmer에서는 database.yml에 master slave를 한단계 더 만들어서 설정해서 한 파일에 다 넣었는데요. 얘는 database.yml에는 마스터디비정보만 넣고, shards.yml파일을 새로 만들어서 slave디비정보를 넣어줍니다.
master는 그대로 database.yml에 설정합니다.
database.yml
default: &default adapter: mysql encoding: utf8 database: mudchobo username: root password: 1234 host: 마스터주소 port: 3306 pool: 5 timeout: 5000 development: <<: *default test: <<: *default database: mudchobo_test production: <<: *default database: mudchobo_production
slave들은 따로 파일을 만들어서 관리합니다.
config/shards.xml
default: &default adapter: mysql2 encoding: utf8 username: root password: 1234 host: 슬레이브주소 port: 3306 pool: 5 timeout: 5000 octopus: replicated: true environments: - development - production development: slave1: <<: *default database: mudchobo production: slave1: <<: *default database: mudchobo_production
설정은 비슷한데, 멀티 slave를 둘 수 있어서 환경 아래 slave1, slave2 등 여러 개를 두개 되면 select하는 것들에 대해서 알아서 선택해서 접속해서 데이터를 가져옵니다.
replicated: true로 사용해야 가능하고, 혹시 특정 모델에만 리플리케이션을 하고 싶으면 fully_replicated: false를 추가하고, 리플리케이션 허용 하는 것에 대해서는 모델에서 아래와 같이 넣어주면 됩니다.
#This class is replicated, writes to master and reads to slave. class Cat < ActiveRecord::Base replicated_model() end
5. db migration 생성 및 INSERT SELECT 테스트.
테이블 생성해서 테스트 해봅시다. 모델은 간단히 그냥 dummy라는 테이블을 만들고, name칼럼을 하나 넣어봅시다.
$ rails g model dummy name:string invoke active_record create db/migrate/20150403162358_create_dummies.rb create app/models/dummy.rb invoke test_unit create test/models/dummy_test.rb create test/fixtures/dummies.yml $ rake db:migrate == 20150403162358 CreateDummies: migrating - Shard: master ==================== -- create_table(:dummies) -> 0.0061s == 20150403162358 CreateDummies: migrated (0.0062s) - Shard: master ===========
그러면 마스터에 테이블이 하나 생성이 되는데요. 물론 리플이 되어있으면 슬레이브에도 있겠죠. 데이터를 넣어보고 가져와봅시다.
$ rails c Loading development environment (Rails 4.1.7) irb(main):001:0> Dummy.create(name: 'fucking') (0.3ms) BEGIN SQL (1.2ms) INSERT INTO `dummies` (`created_at`, `name`, `updated_at`) VALUES ('2015-04-03 16:29:27', 'fucking', '2015-04-03 16:29:27') (0.6ms) COMMIT => #<Dummy id: 2, name: "fucking", created_at: "2015-04-03 16:29:27", updated_at: "2015-04-03 16:29:27"> irb(main):002:0> Dummy.find(2) [Shard: slave1] Dummy Load (0.6ms) SELECT `dummies`.* FROM `dummies` WHERE `dummies`.`id` = 2 LIMIT 1 => #<Dummy id: 2, name: "fucking", created_at: "2015-04-03 16:29:27", updated_at: "2015-04-03 16:29:27"> irb(main):003:0>
잘 되는데....슬레이브에서 가져오는지 잘 모르겠네요... 슬레이브 서버를 죽여버릴까......-_-
irb(main):008:0* Dummy.create(name: 'yes!') (1.0ms) BEGIN SQL (0.9ms) INSERT INTO `dummies` (`created_at`, `name`, `updated_at`) VALUES ('2015-04-03 16:31:55', 'yes!', '2015-04-03 16:31:55') (1.2ms) COMMIT => #<Dummy id: 3, name: "yes!", created_at: "2015-04-03 16:31:55", updated_at: "2015-04-03 16:31:55"> irb(main):009:0> Dummy.find(3) [Shard: slave1] Dummy Load (0.2ms) SELECT `dummies`.* FROM `dummies` WHERE `dummies`.`id` = 3 LIMIT 1 Mysql2::Error: closed MySQL connection: SELECT `dummies`.* FROM `dummies` WHERE `dummies`.`id` = 3 LIMIT 1
아 잘되네요.
그 외에도 slave서버를 선택해서 사용할 수 있는 using메소드도 있어요.
뭔가 별거 아니지만 장황하게 썼다-_-
PS. 한 프로젝트에서 멀티 디비를 사용하는 프로젝트에서도 유용하게 사용할 수 있어요. 그 Octopus_establish가 있는데, 그걸 통해서 해당 모델에서는 그것에 대한 슬레이브만 접근할 수 있는 설정도 할 수 있어요! 유용하게 쓰세요!