ø Downtime migrations - Ruby Conf 2015
-
Upload
jonatas-paganini -
Category
Technology
-
view
432 -
download
1
Transcript of ø Downtime migrations - Ruby Conf 2015
![Page 1: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/1.jpg)
ø downtimeJônatas Davi Paganini
jonatasjonatasdp
![Page 2: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/2.jpg)
8 dev teams
![Page 3: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/3.jpg)
10 deploys / day
![Page 4: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/4.jpg)
RD Station
![Page 5: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/5.jpg)
+2m mail / day
![Page 6: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/6.jpg)
+700 external services
integrations
![Page 7: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/7.jpg)
+N callbacks
![Page 8: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/8.jpg)
Availability is
REQUIRED
![Page 9: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/9.jpg)
99,9%
99,5%
99,0%
98,6%
98,0%
97,0%
99,99%
00:43:00
03:36:00
07:12:00
10:00:00
14:24:00
21:36:00
00:04:32
Availability
![Page 10: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/10.jpg)
99.999???
![Page 11: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/11.jpg)
availability =( total_time - timeout / total_time ) * 100
![Page 12: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/12.jpg)
ø downtime
![Page 13: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/13.jpg)
mindset
![Page 14: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/14.jpg)
NO schedulemaintenance
![Page 15: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/15.jpg)
avoid: all || nothing
![Page 16: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/16.jpg)
build reversible things
![Page 17: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/17.jpg)
build incremental migrations
![Page 18: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/18.jpg)
RubyConf 2012
![Page 19: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/19.jpg)
compatible versions
![Page 20: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/20.jpg)
http://shipit.resultadosdigitais.com.br/blog/migrando-com-zero-downtime
talk is <cheap>!
![Page 21: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/21.jpg)
show me the code!!!
![Page 22: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/22.jpg)
Migration
add_column :people, :full_name, :string
![Page 23: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/23.jpg)
Update data
Person.all.each do |person| person.full_name = "#{person.first_name} #{person.last_name}" person.saveend
![Page 24: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/24.jpg)
350 million updates!!!
![Page 25: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/25.jpg)
WTF time?!
![Page 26: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/26.jpg)
Let’s improve it!
Person.all.each do |person| person.full_name = "#{person.first_name} #{person.last_name}" person.saveend
![Page 27: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/27.jpg)
Select RIGHT attributes!
![Page 28: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/28.jpg)
Update 0.1
Person.select("id,first_name,last_name").each do |person| person.full_name = "#{person.first_name} #{person.last_name}" person.saveend
![Page 29: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/29.jpg)
update_attribute instead of save
![Page 30: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/30.jpg)
Update 0.2
Person.select("id,first_name,last_name").each do |person| person.update_attribute "full_name", "#{person.first_name} #{person.last_name}"end
![Page 31: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/31.jpg)
find in batches
![Page 32: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/32.jpg)
avoid transaction
overhead
![Page 33: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/33.jpg)
Update 0.3
Person.select("id,first_name,last_name").find_in_batches do |people| People.transaction do people.each do |person| person.update_attribute "full_name", "#{person.first_name} #{person.last_name}" end endend
![Page 34: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/34.jpg)
FAILURE resilient
![Page 35: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/35.jpg)
Update 0.4
Person.where(full_name: nil).select("id,first_name,last_name").find_in_batches do |people| People.transaction do people.each do |person| person.update_attribute "full_name", "#{person.first_name} #{person.last_name}" end endend
![Page 36: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/36.jpg)
explore connection pool
![Page 37: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/37.jpg)
Update 0.5
update_sql = "UPDATE people set full_name ="
Person.where(full_name: nil).select("id,first_name,last_name").find_in_batches do |people| People.transaction do people.each(ActiveRecord::Base.connection_config[:pool]) do |person| ActiveRecord::Base.connection_pool.with_connection do |conn| set_full_name = conn.quote("#{person.first_name} #{person.last_name}") conn.execute("#{update_sql} #{set_full_name} where id = #{person.id} ") end end endend
![Page 38: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/38.jpg)
model hook
![Page 39: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/39.jpg)
Model
class Person < ActiveRecord::Base before_save :update_full_name
def update_full_name self.full_name = "#{first_name} #{last_name}" endend
![Page 40: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/40.jpg)
rollout control
![Page 41: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/41.jpg)
Rollout
class Rollout def enabled?(feature, context) redis.sismember(feature, context) rescue Redis::BaseError false end
def enable(feature, context) redis.sadd(feature) end def disable(feature, context) redis.srem(feature) end
private def redis Redis::Namespace.new("rollout", redis: $redis) endend
![Page 42: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/42.jpg)
rollout use
![Page 43: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/43.jpg)
if:
before_save :update_full_name, if: -> { Rollout.enabled? "started_migration", "global" }
![Page 44: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/44.jpg)
deploy steps
![Page 45: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/45.jpg)
smoothlysteps
![Page 46: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/46.jpg)
PR #1
add new column
![Page 47: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/47.jpg)
PR #2
write old & new columns
![Page 48: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/48.jpg)
PR #3
migrate data
![Page 49: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/49.jpg)
PR #4
read from new column
![Page 50: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/50.jpg)
PR #5
remove old column
![Page 51: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/51.jpg)
PR #6
remove rollout code, cache
![Page 52: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/52.jpg)
Conclusion
![Page 53: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/53.jpg)
Embrace migrations ● smoothly● incremental● safe● resilient
![Page 54: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/54.jpg)
Avoid migrations
● all || nothing● ! roll outable features
![Page 55: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/55.jpg)
REFERENCES
blog.codeship.com/rails-migrations-zero-downtime/
shipit.resultadosdigitais.com.br/blog/migrando-com-zero-downtime/
confreaks.tv/videos/railsconf2012-zero-downtime-deploys-for-rails-apps
![Page 56: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/56.jpg)
?
![Page 57: ø Downtime migrations - Ruby Conf 2015](https://reader031.fdocuments.us/reader031/viewer/2022030315/588064c21a28ab0b098b6401/html5/thumbnails/57.jpg)
Thanks!jonatasjonatasdp
ideia.meshipit.resultadosdigitais.com.br