Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Did We Forget the Benefits of RDBMS?

Did We Forget the Benefits of RDBMS?

An overview of things we need to consider when doing zero downtime web application deployments and how RDBMS can help us.

Damir

June 19, 2014
Tweet

More Decks by Damir

Other Decks in Programming

Transcript

  1. How to Achieve High Availability? Resilient and scalable server architecture

    Good software development process Zero-downtime deployments
  2. App Deployment Replace old code with the new one Change

    the database schema (execute migrations)
  3. Zero-downtime Deployments "Zero" as in 0, not as in "Coke

    Zero" (3kc/l) No request is dropped due to code change No request should be fail due to application error (500 status)
  4. No Dropped Requests Start workers with the new code Route

    new requests to the new code Let the old workers finish processing requestes and kill them
  5. No Requests Should Fail Why would a request fail? •

    Codebase/database mismatch • Codebase/user submitted data mismatch (public API change)
  6. "What about migrations? Simple: just throw up a “The site

    is temporarily down for maintenance” page, run the migration, restart Unicorn, then remove the downtime page. Same as it ever was." https://github.com/blog/517-unicorn
  7. Codebase/Database Mismatch When do we execute migrations? • Before code

    deployment • After code deployment • It depends
  8. Recipe: Remove a Column 1. Tell Rails not to cache

    a column (needs a hack in code) 2. Deploy code that doesn't use a column 3. Execute migrations after deployment
  9. Recipe: Add a Column 1. Execute the migration* 2. Deploy

    the new code ! *A nifty helper to execute migrations remotely on Heroku: https://gist.github.com/sidonath/8735211
  10. Recipe: Rename a Column 1. Create a new column with

    the new name 2. Change Rails model to write data to both columns 3. Exclude the old column from the column cache 4. Deploy the changed code 5. Migrate data 6. Remove old column
  11. Rename a Column #2 1. Write a migration that uses

    triggers to keep data in sync and migrates the data in a transaction 2. Run the migration 3. Deploy the new code (no hacks necessary!) 4. Run a migration that removes now unnecessary triggers
  12. Step-by-Step Add a column Write a stored procedure (in PL/pgSQL,

    MySQL, T-SQL, PG/SQL) Create AFTER INSERT/UPDATE/DELETE trigger to run the procedure Execute INSERT/UPDATE to migrate the data COMMIT the transaction
  13. execute <<-UPDATE_TABLE_TRIGGER_FUNCTION CREATE OR REPLACE FUNCTION copy_transaction_to_entry() RETURNS trigger AS

    $copy_transaction_to_entry$ BEGIN ! INSERT INTO plutus_entries (id, description) VALUES (NEW.id, NEW.description); ! SELECT setval('plutus_entries_id_seq', NEW.id); ! RETURN NEW; END; $copy_transaction_to_entry$ LANGUAGE plpgsql; UPDATE_TABLE_TRIGGER_FUNCTION
  14. execute <<-UPDATE_COLUMN_TRIGGER_FUNCTION CREATE OR REPLACE FUNCTION copy_transaction_id_to_entry_id() RETURNS trigger AS

    $copy_transaction_id_to_entry_id$ BEGIN ! NEW.entry_id := NEW.transaction_id; RETURN NEW; ! END; $copy_transaction_id_to_entry_id$ LANGUAGE plpgsql; UPDATE_COLUMN_TRIGGER_FUNCTION
  15. execute <<-TRIGGERS CREATE TRIGGER replicate_plutus_transactions AFTER INSERT ON plutus_transactions FOR

    EACH ROW EXECUTE PROCEDURE copy_transaction_to_entry(); ! CREATE TRIGGER replicate_plutus_transaction_id BEFORE INSERT ON plutus_amounts FOR EACH ROW EXECUTE PROCEDURE copy_transaction_id_to_entry_id(); TRIGGERS
  16. execute <<-MIGRATEDATA INSERT INTO plutus_entries SELECT * FROM plutus_transactions WHERE

    id NOT IN (SELECT id FROM plutus_entries); ! SELECT setval('plutus_entries_id_seq', nextval('plutus_transactions_id_seq'), false); ! UPDATE plutus_amounts SET entry_id = transaction_id; MIGRATEDATA