krug 02 2014

44
Multi-tenancy in Rails with PostgreSQL Schemas Tomasz Giereś

Upload: tomasz-gieres

Post on 15-Jan-2015

465 views

Category:

Documents


4 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Krug 02 2014

Multi-tenancy in Rails with PostgreSQL

Schemas

Tomasz Giereś

Page 2: Krug 02 2014

● Tomasz Giereś● tomaszgieres (github/twitter)● [email protected]● almost 2 years at Lunar Logic● mainly developing Ruby on Rails

applications● also AngularJS, Backbone, Chef, bash,

anything needed● 10+ projects● work with clients

Me

Page 3: Krug 02 2014

● 50 lines of source code,● 1 meme,● 45 slides,● 30-40 minutes,● ask questions during the presentation,● feedback welcome

This talk and presentation

Page 4: Krug 02 2014

Meme

Page 5: Krug 02 2014

schema != schema.rb

Page 6: Krug 02 2014

The problem

1. You have a blog.2. Your friend wants a blog too.

Page 7: Krug 02 2014

Multiple instances

Page 8: Krug 02 2014

Multiple instances

1. Rent an another server / create new heroku application / whatever,

2. Buy a domain,3. Configure everything,4. Deploy a copy of the blog engine there.

Page 9: Krug 02 2014

Multiple instances

● Very easy at the beginning,● fixed price per instance* (server / hardware /

database / licences / external services ),● $100 to host a blog with 50 000 UU for you,● $100 to host a blog with 5 UU for your friend,● $100 dollars for every new instance,● deploy, administrate, backup separately,● separate admin panels etc., no easy way to

i.e. collect data from several applications

* Instance = application process(es) + database + (...)

Page 10: Krug 02 2014

Multiple instances

Page 11: Krug 02 2014

Multitenancy

Page 12: Krug 02 2014

Multitenancy

● One application instance serves all the blogs,

● One database for all the blogs,● No need to pay for the external services

separately?,● Easier to scale:

○ count traffic for all the blogs,○ just add more heroku dynos or application processes

when needed

Page 13: Krug 02 2014

Multitenancy

Page 14: Krug 02 2014

Multitenancy

1. Add root element to data structures:● User has a blog_id● Post has a blog_id● etc.

2. At storage and configuration level● keep the data for every tenant in a separate

storage ● dynamically switch the storage before

accessing the data

Page 15: Krug 02 2014

PostgreSQL schemas

Page 16: Krug 02 2014

● a namespace● a group of tables● an extra layer between a database and a

table● just an extra dot :)

○ <table_name>.<column_name>○ <schema_name>.<table_name>.<column_name>

PostgreSQL schemas

Page 17: Krug 02 2014

PostgreSQL schemas

● every tenant uses its own schema,● tables with common data are not in schemas

( in fact they are in ‘public’ schema )

Page 18: Krug 02 2014

PostgreSQL schemas

Page 19: Krug 02 2014

PostgreSQL schemas

Page 20: Krug 02 2014

PostgreSQL schemasanother_database=# CREATE DATABASE blogs OWNER postgres;CREATE DATABASE

blogs=# CREATE TABLE administrators (name varchar(40));CREATE TABLE

blogs=# INSERT INTO administrators (name) VALUES ('John');INSERT 0 1

Page 21: Krug 02 2014

PostgreSQL schemas

Page 22: Krug 02 2014

PostgreSQL schemasblogs=# CREATE SCHEMA rails_tips;CREATE SCHEMA

blogs=# CREATE TABLE rails_tips.posts ( title varchar(40),content text );CREATE TABLE

blogs=# INSERT INTO rails_tips.posts (title, content) VALUES ('Active Record basics', 'blah blah');INSERT 0 1

Page 23: Krug 02 2014

PostgreSQL schemas

Page 24: Krug 02 2014

PostgreSQL schemasblogs=# CREATE SCHEMA angularjs_tips;CREATE SCHEMA

blogs=# CREATE TABLE angularjs_tips.posts ( title varchar(40), content text );CREATE TABLE

blogs=# INSERT INTO angularjs_tips.posts (title, content) VALUES ('Active Record basics', 'blah blah');INSERT 0 1

Page 25: Krug 02 2014

PostgreSQL schemasblogs=# SELECT * FROM administrators;

name------ John(1 row)

Page 26: Krug 02 2014

PostgreSQL schemas

blogs=# SELECT * FROM angularjs_tips.posts;

title | content---------------+----------- Scopes basics | blah blah(1 row)

Page 27: Krug 02 2014

PostgreSQL schemas

Repeating schema name all the time is annyoing.

Page 28: Krug 02 2014

PostgreSQL schemas

united_states=# SELECT * FROM posts;

ERROR: relation "posts" does not existLINE 1: SELECT * FROM posts; ^

Page 29: Krug 02 2014

PostgreSQL schemas

blogs=# SHOW search_path;

search_path---------------- "$user",public(1 row)

Page 30: Krug 02 2014

PostgreSQL schemas

blogs=# SET search_path TO rails_tips, public;SET

blogs=# SELECT * FROM posts;

title | content----------------------+----------- Active Record basics | blah blah(1 row)

Page 31: Krug 02 2014

PostgreSQL schemas

Page 32: Krug 02 2014

Practice

Page 33: Krug 02 2014

Practice

● usually used with subdomains,● a client organization / a workspace / any

isolated unit = tenant ?● simpler application design and architecture,● less chance for the data leak

Page 34: Krug 02 2014

Practice

Page 35: Krug 02 2014

Rails

Wrocław

Page 36: Krug 02 2014

Rails

Active Record + pg gem:● supports schemas (create, drop, list),● can manipulate search path,● people prefer to execute SQL statements

anyway,● supports the same operations on the tables

within schema as on the public ones

Page 37: Krug 02 2014

RailsFrom Railscast:

#389 Multitenancy with PostgreSQL

with some modifications

Page 38: Krug 02 2014

Rails

Page 39: Krug 02 2014

Rails

Page 40: Krug 02 2014

RailsIt’s common to set search path

and current tenantin rack middleware

Page 41: Krug 02 2014

RailsMigrations

Page 42: Krug 02 2014

Rails

Page 43: Krug 02 2014

Useful information

● influitive / apartment (gem)● pow server● classes and methods to work in console● don’t forget about security● subdomains and schemas in testing

environment (lots of helpers needed),● rescue, sidekiq