SlideShare una empresa de Scribd logo
1 de 56
DISTRIBUTED
               PATTERNS YOU
               SHOULD KNOW
                           Eric Redmond
                            @coderoshi

                       http://git.io/MYrjpQ

Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
h	
  =	
  NaiveHash.new(("A".."J").to_a)
                 tracknodes	
  =	
  Array.new(100000)

                 100000.times	
  do	
  |i|
                 	
  	
  tracknodes[i]	
  =	
  h.node(i)
                 end

                 h.add("K")

                 misses	
  =	
  0
                 100000.times	
  do	
  |i|
                 	
  	
  misses	
  +=	
  1	
  if	
  tracknodes[i]	
  !=	
  h.node(i)
                 end

                 puts	
  "misses:	
  #{(misses.to_f/100000)	
  *	
  100}%"



                 misses:	
  90.922%

Monday, April 22, 13
2160             0
                                                 a single partition
                                                                      Node 0

                                                                      Node 1
                       ring with 32 partitions
                                                                      Node 2


                                                 SHA1(Key)



                              2160/2


Monday, April 22, 13
2160             0
                                                 a single partition
                                                                      Node 0

                                                                      Node 1
                       ring with 32 partitions
                                                                      Node 2

                                                                      Node 3
                                                 SHA1(Key)



                              2160/2


Monday, April 22, 13
SHA1BITS	
  =	
  160
        class	
  PartitionedConsistentHash                                             h	
  =	
  PartitionedConsistentHash.new(("A".."J").to_a)
        	
  	
  def	
  initialize(nodes=[],	
  partitions=32)                          nodes	
  =	
  Array.new(100000)
        	
  	
  	
  	
  @partitions	
  =	
  partitions                                 100000.times	
  do	
  |i|
        	
  	
  	
  	
  @nodes,	
  @ring	
  =	
  nodes.clone.sort,	
  {}
        	
  	
  	
  	
  @power	
  =	
  SHA1BITS	
  -­‐	
  Math.log2(partitions).to_i
                                                                                       	
  	
  nodes[i]	
  =	
  h.node(i)
        	
  	
  	
  	
  @partitions.times	
  do	
  |i|                                 end
        	
  	
  	
  	
  	
  	
  @ring[range(i)]	
  =	
  @nodes[0]                      puts	
  "add	
  K"
        	
  	
  	
  	
  	
  	
  @nodes	
  <<	
  @nodes.shift
        	
  	
  	
  	
  end
                                                                                       h.add("K")
        	
  	
  	
  	
  @nodes.sort!                                                   misses	
  =	
  0
        	
  	
  end                                                                    100000.times	
  do	
  |i|
                                                                                       	
  	
  misses	
  +=	
  1	
  if	
  nodes[i]	
  !=	
  h.node(i)
        	
  	
  def	
  range(partition)
        	
  	
  	
  	
  (partition*(2**@power)..(partition+1)*(2**@power)-­‐1)         end
        	
  	
  end                                                                    puts	
  "misses:	
  #{(misses.to_f/100000)	
  *	
  100}%n"
        	
  	
  def	
  hash(key)
        	
  	
  	
  	
  Digest::SHA1.hexdigest(key.to_s).hex
        	
  	
  end                                                                    misses:	
  9.473%
        	
  	
  def	
  add(node)
        	
  	
  	
  	
  @nodes	
  <<	
  node
        	
  	
  	
  	
  partition_pow	
  =	
  Math.log2(@partitions)
        	
  	
  	
  	
  pow	
  =	
  SHA1BITS	
  -­‐	
  partition_pow.to_i
        	
  	
  	
  	
  (0..@partitions).step(@nodes.length)	
  do	
  |i|
        	
  	
  	
  	
  	
  	
  @ring[range(i,	
  pow)]	
  =	
  node
        	
  	
  	
  	
  end
        	
  	
  end

        	
  	
  def	
  node(keystr)
        	
  	
  	
  	
  return	
  nil	
  if	
  @ring.empty?
        	
  	
  	
  	
  key	
  =	
  hash(keystr)
        	
  	
  	
  	
  @ring.each	
  do	
  |range,	
  node|
        	
  	
  	
  	
  	
  	
  return	
  node	
  if	
  range.cover?(key)
        	
  	
  	
  	
  end
        	
  	
  end
        end




Monday, April 22, 13
class	
  Node

    	
  	
  def	
  initialize(name,	
  nodes=[],	
  partitions=32)
    	
  	
  	
  	
  @name	
  =	
  name
    	
  	
  	
  	
  @data	
  =	
  {}
    	
  	
  	
  	
  @ring	
  =	
  ConsistentHash.new(nodes,	
  partitions)
    	
  	
  end

    	
  	
  def	
  put(key,	
  value)
    	
  	
  	
  	
  if	
  @name	
  ==	
  @ring.node(key)
    	
  	
  	
  	
  	
  	
  puts	
  "put	
  #{key}	
  #{value}"
    	
  	
  	
  	
  	
  	
  @data[	
  @ring.hash(key)	
  ]	
  =	
  value
    	
  	
  	
  	
  end
    	
  	
  end

    	
  	
  def	
  get(key)
    	
  	
  	
  	
  if	
  @name	
  ==	
  @ring.node(key)
    	
  	
  	
  	
  	
  	
  puts	
  "get	
  #{key}"
    	
  	
  	
  	
  	
  	
  @data[@ring.hash(key)]
    	
  	
  	
  	
  end
    	
  	
  end

    end



Monday, April 22, 13
nodeA	
  =	
  Node.new(	
  'A',	
  ['A',	
  'B',	
  'C']	
  )
          nodeB	
  =	
  Node.new(	
  'B',	
  ['A',	
  'B',	
  'C']	
  )
          nodeC	
  =	
  Node.new(	
  'C',	
  ['A',	
  'B',	
  'C']	
  )


          nodeA.put(	
  "foo",	
  "bar"	
  )
          p	
  nodeA.get(	
  "foo"	
  )	
  	
  	
  #	
  nil


          nodeB.put(	
  "foo",	
  "bar"	
  )
          p	
  nodeB.get(	
  "foo"	
  )	
  	
  	
  #	
  "bar"


          nodeC.put(	
  "foo",	
  "bar"	
  )
          p	
  nodeC.get(	
  "foo"	
  )	
  	
  	
  #	
  nil




Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Request

                       Client             Service

                                 Reply




Monday, April 22, 13
module	
  Services
      	
  	
  def	
  connect(port=2200,	
  ip="127.0.0.1")
      	
  	
  	
  	
  ctx	
  =	
  ZMQ::Context.new
      	
  	
  	
  	
  sock	
  =	
  ctx.socket(	
  ZMQ::REQ	
  )
      	
  	
  	
  	
  sock.connect(	
  "tcp://#{ip}:#{port}"	
  )
      	
  	
  	
  	
  sock
      	
  	
  end

      	
  	
  def	
  service(port)
      	
  	
  	
  	
  thread	
  do
      	
  	
  	
  	
  	
  	
  ctx	
  =	
  ZMQ::Context.new
      	
  	
  	
  	
  	
  	
  rep	
  =	
  ctx.socket(	
  ZMQ::REP	
  )
      	
  	
  	
  	
  	
  	
  rep.bind(	
  "tcp://127.0.0.1:#{port}"	
  )
      	
  	
  	
  	
  	
  	
  while	
  line	
  =	
  rep.recv
      	
  	
  	
  	
  	
  	
  	
  	
  msg,	
  payload	
  =	
  line.split('	
  ',	
  2)
      	
  	
  	
  	
  	
  	
  	
  	
  send(	
  msg.to_sym,	
  rep,	
  payload	
  )	
  	
  	
  	
  	
  #	
  EVVVIILLLL!!!
      	
  	
  	
  	
  	
  	
  end
      	
  	
  	
  	
  end
      	
  	
  end

      	
  	
  def	
  method_missing(method,	
  *args,	
  &block)
      	
  	
  	
  	
  socket,	
  payload	
  =	
  args
      	
  	
  	
  	
  payload.send(	
  "bad	
  message"	
  )	
  if	
  payload
      	
  	
  end
      end

Monday, April 22, 13
class	
  Node
  	
  	
  include	
  Configuration
  	
  	
  include	
  Threads
  	
  	
  include	
  Services

  	
  	
  def	
  start()
  	
  	
  	
  	
  service(	
  config("port")	
  )
  	
  	
  	
  	
  puts	
  "#{@name}	
  started"
  	
  	
  	
  	
  join_threads()
  	
  	
  end

  	
  	
  def	
  remote_call(name,	
  message)
  	
  	
  	
  	
  puts	
  "#{name}	
  <=	
  #{message}"
  	
  	
  	
  	
  req	
  =	
  connect(config("port",	
  name),	
  config("ip",	
  name))
  	
  	
  	
  	
  resp	
  =	
  req.send(message)	
  &&	
  req.recv
  	
  	
  	
  	
  req.close
  	
  	
  	
  	
  resp
  	
  	
  end

  	
  	
  #	
  ...




Monday, April 22, 13
 	
  #	
  ...

   	
  	
  def	
  put(socket,	
  payload)
   	
  	
  	
  	
  key,	
  value	
  =	
  payload.split('	
  ',	
  2)
   	
  	
  	
  	
  socket.send(	
  do_put(key,	
  value).to_s	
  )
   	
  	
  end


   	
  	
  def	
  do_put(key,	
  value)
   	
  	
  	
  	
  node	
  =	
  @ring.node(key)
   	
  	
  	
  	
  if	
  node	
  ==	
  @name
   	
  	
  	
  	
  	
  	
  puts	
  "put	
  #{key}	
  #{value}"
   	
  	
  	
  	
  	
  	
  @data[@ring.hash(key)]	
  =	
  value
   	
  	
  	
  	
  else
   	
  	
  	
  	
  	
  	
  remote_call(node,	
  "put	
  #{key}	
  #{value}"	
  )
   	
  	
  	
  	
  end
   	
  	
  end




Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Subscriber




                       Publisher   Subscriber




                                   Subscriber




Monday, April 22, 13
class	
  Node
    	
  	
  #	
  ...
    	
  	
  def	
  coordinate_cluster(pub_port,	
  rep_port)
    	
  	
  	
  	
  thread	
  do
    	
  	
  	
  	
  	
  	
  ctx	
  =	
  ZMQ::Context.new
    	
  	
  	
  	
  	
  	
  pub	
  =	
  ctx.socket(	
  ZMQ::PUB	
  )
    	
  	
  	
  	
  	
  	
  pub.bind(	
  "tcp://*:#{pub_port}"	
  )
    	
  	
  	
  	
  	
  	
  rep	
  =	
  ctx.socket(	
  ZMQ::REP	
  )
    	
  	
  	
  	
  	
  	
  rep.bind(	
  "tcp://*:#{rep_port}"	
  )

    	
  	
  	
  	
  	
  	
  while	
  line	
  =	
  rep.recv
    	
  	
  	
  	
  	
  	
  	
  	
  msg,	
  node	
  =	
  line.split('	
  ',	
  2)
    	
  	
  	
  	
  	
  	
  	
  	
  nodes	
  =	
  @ring.nodes
    	
  	
  	
  	
  	
  	
  	
  	
  case	
  msg
    	
  	
  	
  	
  	
  	
  	
  	
  when	
  'join'
    	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  nodes	
  =	
  (nodes	
  <<	
  node).uniq.sort
    	
  	
  	
  	
  	
  	
  	
  	
  when	
  'down'
    	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  nodes	
  -­‐=	
  [node]
    	
  	
  	
  	
  	
  	
  	
  	
  end
    	
  	
  	
  	
  	
  	
  	
  	
  @ring.cluster(nodes)

    	
  	
  	
  	
  	
  	
  	
  	
  pub.send(	
  "ring	
  "	
  +	
  nodes.join(','))
    	
  	
  	
  	
  	
  	
  	
  	
  rep.send(	
  "true"	
  )
    	
  	
  	
  	
  	
  	
  end
    	
  	
  	
  	
  end
    	
  	
  end
Monday, April 22, 13
class	
  Node
    	
  	
  #	
  ...
    	
  	
  def	
  track_cluster(sub_port)
    	
  	
  	
  	
  thread	
  do
    	
  	
  	
  	
  	
  	
  ctx	
  =	
  ZMQ::Context.new
    	
  	
  	
  	
  	
  	
  sub	
  =	
  ctx.socket(	
  ZMQ::SUB	
  )
    	
  	
  	
  	
  	
  	
  sub.connect(	
  "tcp://127.0.0.1:#{sub_port}"	
  )
    	
  	
  	
  	
  	
  	
  sub.setsockopt(	
  ZMQ::SUBSCRIBE,	
  "ring"	
  )
    	
  	
  	
  	
  	
  	
  
    	
  	
  	
  	
  	
  	
  while	
  line	
  =	
  sub.recv
    	
  	
  	
  	
  	
  	
  	
  	
  _,	
  nodes	
  =	
  line.split('	
  ',	
  2)
    	
  	
  	
  	
  	
  	
  	
  	
  nodes	
  =	
  nodes.split(',').map{|x|	
  x.strip}
    	
  	
  	
  	
  	
  	
  	
  	
  @ring.cluster(	
  nodes	
  )
    	
  	
  	
  	
  	
  	
  	
  	
  puts	
  "ring	
  changed:	
  #{nodes.inspect}"
    	
  	
  	
  	
  	
  	
  end
    	
  	
  	
  	
  end
    	
  	
  end




Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
 	
  def	
  replicate(message,	
  n)
       	
  	
  	
  	
  list	
  =	
  @ring.pref_list(n)
       	
  	
  	
  	
  results	
  =	
  []
       	
  	
  	
  	
  while	
  replicate_node	
  =	
  list.shift
       	
  	
  	
  	
  	
  	
  results	
  <<	
  remote_call(replicate_node,	
  message)
       	
  	
  	
  	
  end
       	
  	
  	
  	
  results
       	
  	
  end




Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
WHAT TO EAT FOR DINNER?
   •   Adam wants Pizza

         {value:"pizza", vclock:{adam:1}}

   •   Barb wants Tacos

         {value:"tacos", vclock:{barb:1}}

   •   Adam gets the value, the system can’t resolve, so he gets bolth

         [{value:"pizza", vclock:{adam:1}},
          {value:"tacos", vclock:{barb:1}}]

   •   Adam resolves the value however he wants

         {value:"taco pizza", vclock:{adam:2, barb:1}}

Monday, April 22, 13
#	
  artificially	
  create	
  a	
  conflict	
  with	
  vclocks
          req.send('put	
  1	
  foo	
  {"B":1}	
  hello1')	
  &&	
  req.recv
          req.send('put	
  1	
  foo	
  {"C":1}	
  hello2')	
  &&	
  req.recv
          puts	
  req.send("get	
  2	
  foo")	
  &&	
  req.recv

          sleep	
  5

          #	
  resolve	
  the	
  conflict	
  by	
  decending	
  from	
  one	
  of	
  the	
  vclocks
          req.send('put	
  2	
  foo	
  {"B":3}	
  hello1')	
  &&	
  req.recv
          puts	
  req.send("get	
  2	
  foo")	
  &&	
  req.recv




Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
Monday, April 22, 13
1.

                2.

                3.

                4.

Monday, April 22, 13
Monday, April 22, 13
MERKEL TREE


    •A         tree of hashes

    • Periodicallypassed
        between nodes

    • Differences       are “repaired”



Monday, April 22, 13
Monday, April 22, 13
array	
  	
  =	
  [{value:1},{value:3},{value:5}]

           mapped	
  =	
  array.map{|obj|	
  obj[:value]}
           #	
  [1,	
  3,	
  5]

           mapped.reduce(0){|sum,value|	
  sum	
  +	
  value}
           #	
  9




Monday, April 22, 13
Monday, April 22, 13
module	
  Mapreduce

   	
  	
  def	
  mr(socket,	
  payload)
   	
  	
  	
  	
  map_func,	
  reduce_func	
  =	
  payload.split(/;s+reduce/,	
  2)
   	
  	
  	
  	
  reduce_func	
  =	
  "reduce#{reduce_func}"
   	
  	
  	
  	
  socket.send(	
  Reduce.new(reduce_func,	
  call_maps(map_func)).call.to_s	
  )
   	
  	
  end

   	
  	
  def	
  map(socket,	
  payload)
   	
  	
  	
  	
  socket.send(	
  Map.new(payload,	
  @data).call.to_s	
  )
   	
  	
  end

   	
  	
  #	
  run	
  in	
  parallel,	
  then	
  join	
  results
   	
  	
  def	
  call_maps(map_func)
   	
  	
  	
  	
  results	
  =	
  []
   	
  	
  	
  	
  nodes	
  =	
  @ring.nodes	
  -­‐	
  [@name]
   	
  	
  	
  	
  nodes.map	
  {|node|
   	
  	
  	
  	
  	
  	
  Thread.new	
  do
   	
  	
  	
  	
  	
  	
  	
  	
  res	
  =	
  remote_call(node,	
  "map	
  #{map_func}")
   	
  	
  	
  	
  	
  	
  	
  	
  results	
  +=	
  eval(res)
   	
  	
  	
  	
  	
  	
  end
   	
  	
  	
  	
  }.each{|w|	
  w.join}
   	
  	
  	
  	
  results	
  +=	
  Map.new(map_func,	
  @data).call
   	
  	
  end
   end

Monday, April 22, 13
module	
  Mapreduce

   	
  	
  def	
  mr(socket,	
  payload)
   	
  	
  	
  	
  map_func,	
  reduce_func	
  =	
  payload.split(/;s+reduce/,	
  2)
   	
  	
  	
  	
  reduce_func	
  =	
  "reduce#{reduce_func}"
   	
  	
  	
  	
  socket.send(	
  Reduce.new(reduce_func,	
  call_maps(map_func)).call.to_s	
  )
   	
  	
  end

   	
  	
  def	
  map(socket,	
  payload)
   	
  	
  	
  	
  socket.send(	
  Map.new(payload,	
  @data).call.to_s	
  )
   	
  	
  end

   	
  	
  #	
  run	
  in	
  parallel,	
  then	
  join	
  results
   	
  	
  def	
  call_maps(map_func)
   	
  	
  	
  	
  results	
  =	
  []
   	
  	
  	
  	
  nodes	
  =	
  @ring.nodes	
  -­‐	
  [@name]
   	
  	
  	
  	
  nodes.map	
  {|node|
   	
  	
  	
  	
  	
  	
  Thread.new	
  do
   	
  	
  	
  	
  	
  	
  	
  	
  res	
  =	
  remote_call(node,	
  "map	
  #{map_func}")
   	
  	
  	
  	
  	
  	
  	
  	
  results	
  +=	
  eval(res)
   	
  	
  	
  	
  	
  	
  end
   	
  	
  	
  	
  }.each{|w|	
  w.join}
   	
  	
  	
  	
  results	
  +=	
  Map.new(map_func,	
  @data).call
   	
  	
  end
   end

Monday, April 22, 13
200.times	
  do	
  |i|
 	
  	
  req.send(	
  "put	
  2	
  key#{i}	
  {}	
  #{i}"	
  )	
  &&	
  req.recv
 end

 req.send(	
  "mr	
  map{|k,v|	
  [1]};	
  reduce{|vs|	
  vs.length}"	
  )
 puts	
  req.recv




Monday, April 22, 13
200.times	
  do	
  |i|
 	
  	
  req.send(	
  "put	
  2	
  key#{i}	
  {}	
  #{i}"	
  )	
  &&	
  req.recv
 end

 req.send(	
  "mr	
  map{|k,v|	
  [1]};	
  reduce{|vs|	
  vs.length}"	
  )
 puts	
  req.recv




Monday, April 22, 13
Monday, April 22, 13
WHAT WE’VE DONE SO FAR
                       http://git.io/MYrjpQ




    • Distributed, Replicated, Self-healing, Conflict-resolving,
        Eventually Consistent Key/Value Datastore... with Mapreduce




Monday, April 22, 13
Key/Value
          Preference List
                                                   Vector Clocks
                           Distributed Hash Ring
        Request/
        Response




          Merkle Tree                     Node Gossip

                       CRDT (coming)               Read Repair

Monday, April 22, 13
basho
                                              @coderoshi




            http://pragprog.com/book/rwdata            http://github.com/coderoshi/little_riak_book




Monday, April 22, 13
I am the very model of a distributed database,
 I've information in my nodes residing out in cyber space,
 While other datastorers keep consistent values just in case,
 It's tolerant partitions and high uptime, that I embrace.




Monday, April 22, 13
I use a SHA-1algorithm, one-sixty bits of hashing space
 consistent hash ensures k/v's are never ever out of place,
 I replicate my data across more than one partition,
 In case a running node or two encounters decommission.




Monday, April 22, 13
My read repairs consistently, at least it does eventually,
  CAP demands you've only 2 to choose from preferentially,
  In short, you get consistency or high availability,
  To claim you can distribute and do both is pure futility.




Monday, April 22, 13
A system such as I is in a steady tiff with Entropy,
   since practically a quorum is consistent only sloppily,
   My favorite solutions are both read repair and AAE,
   My active anti-entropy trades deltas via Merkel Tree.




Monday, April 22, 13
After write, the clients choose their conflict resolution,
  With convergent replicated data types are a solution:
  I only take a change in state, and not results imperforate,
  And merge results to forge a final value that is proximate.




Monday, April 22, 13
How to know a sequence of events w/o employing locks,
 Well naturally, I use Lamport logic ordered vector-clocks.
 I have both sibling values when my v-clocks face a conflict,
 and keep successive values 'til a single one is picked.




Monday, April 22, 13
If values are your query goal then write some mapreduces.
 Invert-indexing values may reduce query obtuseness.
 Distributing a graph or a relation-style structure,
 though somewhat possible provides a weaker juncture.




Monday, April 22, 13
For data of the meta kind, my ring state is a toss up,
   To keep in sync my nodes will chat through protocol gossip.
   I am a mesh type network, not tree/star topological, their
   single points of failure make such choices most illogical.




Monday, April 22, 13
My network ring is just the thing, ensuring writes are quick,
  But know that CAP demands my choice give only 2 to pick.
  In short, I get consistency or high availability,
  To claim I could distribute and do both is just futility.




Monday, April 22, 13

Más contenido relacionado

La actualidad más candente

Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationJacopo Mangiavacchi
 
Clojure for Data Science
Clojure for Data ScienceClojure for Data Science
Clojure for Data Sciencehenrygarner
 
The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185Mahmoud Samir Fayed
 
Mobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobileFest2018
 
Python Asíncrono - Async Python
Python Asíncrono - Async PythonPython Asíncrono - Async Python
Python Asíncrono - Async PythonJavier Abadía
 
Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Roman Elizarov
 
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)ぐだ生 Java入門第三回(文字コードの話)(Keynote版)
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)Makoto Yamazaki
 
Code as data as code.
Code as data as code.Code as data as code.
Code as data as code.Mike Fogus
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4Jan Berdajs
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIEleanor McHugh
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Eelco Visser
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수용 최
 
Os9 2
Os9 2Os9 2
Os9 2issbp
 
The Ring programming language version 1.5.2 book - Part 45 of 181
The Ring programming language version 1.5.2 book - Part 45 of 181The Ring programming language version 1.5.2 book - Part 45 of 181
The Ring programming language version 1.5.2 book - Part 45 of 181Mahmoud Samir Fayed
 

La actualidad más candente (20)

Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML Personalization
 
Clojure for Data Science
Clojure for Data ScienceClojure for Data Science
Clojure for Data Science
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
 
The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185
 
Mobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. Болеутоляющее
 
Python Asíncrono - Async Python
Python Asíncrono - Async PythonPython Asíncrono - Async Python
Python Asíncrono - Async Python
 
Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017
 
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)ぐだ生 Java入門第三回(文字コードの話)(Keynote版)
ぐだ生 Java入門第三回(文字コードの話)(Keynote版)
 
Code as data as code.
Code as data as code.Code as data as code.
Code as data as code.
 
C++ L09-Classes Part2
C++ L09-Classes Part2C++ L09-Classes Part2
C++ L09-Classes Part2
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
 
ROracle
ROracle ROracle
ROracle
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
Os9 2
Os9 2Os9 2
Os9 2
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
The Ring programming language version 1.5.2 book - Part 45 of 181
The Ring programming language version 1.5.2 book - Part 45 of 181The Ring programming language version 1.5.2 book - Part 45 of 181
The Ring programming language version 1.5.2 book - Part 45 of 181
 
C++ L08-Classes Part1
C++ L08-Classes Part1C++ L08-Classes Part1
C++ L08-Classes Part1
 
A tour of Python
A tour of PythonA tour of Python
A tour of Python
 

Destacado

海外僑胞回國參加中華​民國一百年十月慶典事
海外僑胞回國參加中華​民國一百年十月慶典事海外僑胞回國參加中華​民國一百年十月慶典事
海外僑胞回國參加中華​民國一百年十月慶典事anita4711
 
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份anita4711
 
雲端運算
雲端運算雲端運算
雲端運算anita4711
 
電子商務講座(二)
電子商務講座(二) 電子商務講座(二)
電子商務講座(二) anita4711
 
電子商務概論
電子商務概論電子商務概論
電子商務概論anita4711
 
Globalization
GlobalizationGlobalization
Globalizationsaleem908
 

Destacado (6)

海外僑胞回國參加中華​民國一百年十月慶典事
海外僑胞回國參加中華​民國一百年十月慶典事海外僑胞回國參加中華​民國一百年十月慶典事
海外僑胞回國參加中華​民國一百年十月慶典事
 
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份
第31期海外青年技術訓練班宣傳摺頁(電子檔)乙份
 
雲端運算
雲端運算雲端運算
雲端運算
 
電子商務講座(二)
電子商務講座(二) 電子商務講座(二)
電子商務講座(二)
 
電子商務概論
電子商務概論電子商務概論
電子商務概論
 
Globalization
GlobalizationGlobalization
Globalization
 

Similar a DDS-20m

Advanced data structure
Advanced data structureAdvanced data structure
Advanced data structureShakil Ahmed
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)tarcieri
 
Topology Matters in Communication
Topology Matters in CommunicationTopology Matters in Communication
Topology Matters in Communicationcseiitgn
 
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...Revolution Analytics
 
Paul presentation P2P Chord v1
Paul presentation P2P Chord v1Paul presentation P2P Chord v1
Paul presentation P2P Chord v1Paul Yang
 
Introduction to Neural Networks and Deep Learning from Scratch
Introduction to Neural Networks and Deep Learning from ScratchIntroduction to Neural Networks and Deep Learning from Scratch
Introduction to Neural Networks and Deep Learning from ScratchAhmed BESBES
 
Help I keep getting the same error when running a code. Below is the.pdf
Help I keep getting the same error when running a code. Below is the.pdfHelp I keep getting the same error when running a code. Below is the.pdf
Help I keep getting the same error when running a code. Below is the.pdfmail931892
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Java code to find the closest pair using divide and conquer algorith.pdf
Java code to find the closest pair using divide and conquer algorith.pdfJava code to find the closest pair using divide and conquer algorith.pdf
Java code to find the closest pair using divide and conquer algorith.pdffashioncollection2
 
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1Preston Lee
 
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...Mozaic Works
 
Data structures KTU chapter2.PPT
Data structures KTU chapter2.PPTData structures KTU chapter2.PPT
Data structures KTU chapter2.PPTAlbin562191
 
Pydiomatic
PydiomaticPydiomatic
Pydiomaticrik0
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1Ke Wei Louis
 

Similar a DDS-20m (20)

TeraSort
TeraSortTeraSort
TeraSort
 
Hw09 Hadoop + Clojure
Hw09   Hadoop + ClojureHw09   Hadoop + Clojure
Hw09 Hadoop + Clojure
 
Advanced data structure
Advanced data structureAdvanced data structure
Advanced data structure
 
Hadoop + Clojure
Hadoop + ClojureHadoop + Clojure
Hadoop + Clojure
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
Topology Matters in Communication
Topology Matters in CommunicationTopology Matters in Communication
Topology Matters in Communication
 
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
 
Paul presentation P2P Chord v1
Paul presentation P2P Chord v1Paul presentation P2P Chord v1
Paul presentation P2P Chord v1
 
Introduction to Neural Networks and Deep Learning from Scratch
Introduction to Neural Networks and Deep Learning from ScratchIntroduction to Neural Networks and Deep Learning from Scratch
Introduction to Neural Networks and Deep Learning from Scratch
 
Help I keep getting the same error when running a code. Below is the.pdf
Help I keep getting the same error when running a code. Below is the.pdfHelp I keep getting the same error when running a code. Below is the.pdf
Help I keep getting the same error when running a code. Below is the.pdf
 
Monadologie
MonadologieMonadologie
Monadologie
 
Java code to find the closest pair using divide and conquer algorith.pdf
Java code to find the closest pair using divide and conquer algorith.pdfJava code to find the closest pair using divide and conquer algorith.pdf
Java code to find the closest pair using divide and conquer algorith.pdf
 
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1
Ruby Supercomputing - Using The GPU For Massive Performance Speedup v1.1
 
Array
ArrayArray
Array
 
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...
Stefan Kanev: Clojure, ClojureScript and Why They're Awesome at I T.A.K.E. Un...
 
Data structures KTU chapter2.PPT
Data structures KTU chapter2.PPTData structures KTU chapter2.PPT
Data structures KTU chapter2.PPT
 
Pydiomatic
PydiomaticPydiomatic
Pydiomatic
 
Python idiomatico
Python idiomaticoPython idiomatico
Python idiomatico
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1
 
Disjoint sets
Disjoint setsDisjoint sets
Disjoint sets
 

Último

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 

Último (20)

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 

DDS-20m

  • 1. DISTRIBUTED PATTERNS YOU SHOULD KNOW Eric Redmond @coderoshi http://git.io/MYrjpQ Monday, April 22, 13
  • 5. h  =  NaiveHash.new(("A".."J").to_a) tracknodes  =  Array.new(100000) 100000.times  do  |i|    tracknodes[i]  =  h.node(i) end h.add("K") misses  =  0 100000.times  do  |i|    misses  +=  1  if  tracknodes[i]  !=  h.node(i) end puts  "misses:  #{(misses.to_f/100000)  *  100}%" misses:  90.922% Monday, April 22, 13
  • 6. 2160 0 a single partition Node 0 Node 1 ring with 32 partitions Node 2 SHA1(Key) 2160/2 Monday, April 22, 13
  • 7. 2160 0 a single partition Node 0 Node 1 ring with 32 partitions Node 2 Node 3 SHA1(Key) 2160/2 Monday, April 22, 13
  • 8. SHA1BITS  =  160 class  PartitionedConsistentHash h  =  PartitionedConsistentHash.new(("A".."J").to_a)    def  initialize(nodes=[],  partitions=32) nodes  =  Array.new(100000)        @partitions  =  partitions 100000.times  do  |i|        @nodes,  @ring  =  nodes.clone.sort,  {}        @power  =  SHA1BITS  -­‐  Math.log2(partitions).to_i    nodes[i]  =  h.node(i)        @partitions.times  do  |i| end            @ring[range(i)]  =  @nodes[0] puts  "add  K"            @nodes  <<  @nodes.shift        end h.add("K")        @nodes.sort! misses  =  0    end 100000.times  do  |i|    misses  +=  1  if  nodes[i]  !=  h.node(i)    def  range(partition)        (partition*(2**@power)..(partition+1)*(2**@power)-­‐1) end    end puts  "misses:  #{(misses.to_f/100000)  *  100}%n"    def  hash(key)        Digest::SHA1.hexdigest(key.to_s).hex    end misses:  9.473%    def  add(node)        @nodes  <<  node        partition_pow  =  Math.log2(@partitions)        pow  =  SHA1BITS  -­‐  partition_pow.to_i        (0..@partitions).step(@nodes.length)  do  |i|            @ring[range(i,  pow)]  =  node        end    end    def  node(keystr)        return  nil  if  @ring.empty?        key  =  hash(keystr)        @ring.each  do  |range,  node|            return  node  if  range.cover?(key)        end    end end Monday, April 22, 13
  • 9. class  Node    def  initialize(name,  nodes=[],  partitions=32)        @name  =  name        @data  =  {}        @ring  =  ConsistentHash.new(nodes,  partitions)    end    def  put(key,  value)        if  @name  ==  @ring.node(key)            puts  "put  #{key}  #{value}"            @data[  @ring.hash(key)  ]  =  value        end    end    def  get(key)        if  @name  ==  @ring.node(key)            puts  "get  #{key}"            @data[@ring.hash(key)]        end    end end Monday, April 22, 13
  • 10. nodeA  =  Node.new(  'A',  ['A',  'B',  'C']  ) nodeB  =  Node.new(  'B',  ['A',  'B',  'C']  ) nodeC  =  Node.new(  'C',  ['A',  'B',  'C']  ) nodeA.put(  "foo",  "bar"  ) p  nodeA.get(  "foo"  )      #  nil nodeB.put(  "foo",  "bar"  ) p  nodeB.get(  "foo"  )      #  "bar" nodeC.put(  "foo",  "bar"  ) p  nodeC.get(  "foo"  )      #  nil Monday, April 22, 13
  • 13. Request Client Service Reply Monday, April 22, 13
  • 14. module  Services    def  connect(port=2200,  ip="127.0.0.1")        ctx  =  ZMQ::Context.new        sock  =  ctx.socket(  ZMQ::REQ  )        sock.connect(  "tcp://#{ip}:#{port}"  )        sock    end    def  service(port)        thread  do            ctx  =  ZMQ::Context.new            rep  =  ctx.socket(  ZMQ::REP  )            rep.bind(  "tcp://127.0.0.1:#{port}"  )            while  line  =  rep.recv                msg,  payload  =  line.split('  ',  2)                send(  msg.to_sym,  rep,  payload  )          #  EVVVIILLLL!!!            end        end    end    def  method_missing(method,  *args,  &block)        socket,  payload  =  args        payload.send(  "bad  message"  )  if  payload    end end Monday, April 22, 13
  • 15. class  Node    include  Configuration    include  Threads    include  Services    def  start()        service(  config("port")  )        puts  "#{@name}  started"        join_threads()    end    def  remote_call(name,  message)        puts  "#{name}  <=  #{message}"        req  =  connect(config("port",  name),  config("ip",  name))        resp  =  req.send(message)  &&  req.recv        req.close        resp    end    #  ... Monday, April 22, 13
  • 16.    #  ...    def  put(socket,  payload)        key,  value  =  payload.split('  ',  2)        socket.send(  do_put(key,  value).to_s  )    end    def  do_put(key,  value)        node  =  @ring.node(key)        if  node  ==  @name            puts  "put  #{key}  #{value}"            @data[@ring.hash(key)]  =  value        else            remote_call(node,  "put  #{key}  #{value}"  )        end    end Monday, April 22, 13
  • 19. Subscriber Publisher Subscriber Subscriber Monday, April 22, 13
  • 20. class  Node    #  ...    def  coordinate_cluster(pub_port,  rep_port)        thread  do            ctx  =  ZMQ::Context.new            pub  =  ctx.socket(  ZMQ::PUB  )            pub.bind(  "tcp://*:#{pub_port}"  )            rep  =  ctx.socket(  ZMQ::REP  )            rep.bind(  "tcp://*:#{rep_port}"  )            while  line  =  rep.recv                msg,  node  =  line.split('  ',  2)                nodes  =  @ring.nodes                case  msg                when  'join'                    nodes  =  (nodes  <<  node).uniq.sort                when  'down'                    nodes  -­‐=  [node]                end                @ring.cluster(nodes)                pub.send(  "ring  "  +  nodes.join(','))                rep.send(  "true"  )            end        end    end Monday, April 22, 13
  • 21. class  Node    #  ...    def  track_cluster(sub_port)        thread  do            ctx  =  ZMQ::Context.new            sub  =  ctx.socket(  ZMQ::SUB  )            sub.connect(  "tcp://127.0.0.1:#{sub_port}"  )            sub.setsockopt(  ZMQ::SUBSCRIBE,  "ring"  )                        while  line  =  sub.recv                _,  nodes  =  line.split('  ',  2)                nodes  =  nodes.split(',').map{|x|  x.strip}                @ring.cluster(  nodes  )                puts  "ring  changed:  #{nodes.inspect}"            end        end    end Monday, April 22, 13
  • 25.    def  replicate(message,  n)        list  =  @ring.pref_list(n)        results  =  []        while  replicate_node  =  list.shift            results  <<  remote_call(replicate_node,  message)        end        results    end Monday, April 22, 13
  • 29. WHAT TO EAT FOR DINNER? • Adam wants Pizza {value:"pizza", vclock:{adam:1}} • Barb wants Tacos {value:"tacos", vclock:{barb:1}} • Adam gets the value, the system can’t resolve, so he gets bolth [{value:"pizza", vclock:{adam:1}}, {value:"tacos", vclock:{barb:1}}] • Adam resolves the value however he wants {value:"taco pizza", vclock:{adam:2, barb:1}} Monday, April 22, 13
  • 30. #  artificially  create  a  conflict  with  vclocks req.send('put  1  foo  {"B":1}  hello1')  &&  req.recv req.send('put  1  foo  {"C":1}  hello2')  &&  req.recv puts  req.send("get  2  foo")  &&  req.recv sleep  5 #  resolve  the  conflict  by  decending  from  one  of  the  vclocks req.send('put  2  foo  {"B":3}  hello1')  &&  req.recv puts  req.send("get  2  foo")  &&  req.recv Monday, April 22, 13
  • 34. 1. 2. 3. 4. Monday, April 22, 13
  • 36. MERKEL TREE •A tree of hashes • Periodicallypassed between nodes • Differences are “repaired” Monday, April 22, 13
  • 38. array    =  [{value:1},{value:3},{value:5}] mapped  =  array.map{|obj|  obj[:value]} #  [1,  3,  5] mapped.reduce(0){|sum,value|  sum  +  value} #  9 Monday, April 22, 13
  • 40. module  Mapreduce    def  mr(socket,  payload)        map_func,  reduce_func  =  payload.split(/;s+reduce/,  2)        reduce_func  =  "reduce#{reduce_func}"        socket.send(  Reduce.new(reduce_func,  call_maps(map_func)).call.to_s  )    end    def  map(socket,  payload)        socket.send(  Map.new(payload,  @data).call.to_s  )    end    #  run  in  parallel,  then  join  results    def  call_maps(map_func)        results  =  []        nodes  =  @ring.nodes  -­‐  [@name]        nodes.map  {|node|            Thread.new  do                res  =  remote_call(node,  "map  #{map_func}")                results  +=  eval(res)            end        }.each{|w|  w.join}        results  +=  Map.new(map_func,  @data).call    end end Monday, April 22, 13
  • 41. module  Mapreduce    def  mr(socket,  payload)        map_func,  reduce_func  =  payload.split(/;s+reduce/,  2)        reduce_func  =  "reduce#{reduce_func}"        socket.send(  Reduce.new(reduce_func,  call_maps(map_func)).call.to_s  )    end    def  map(socket,  payload)        socket.send(  Map.new(payload,  @data).call.to_s  )    end    #  run  in  parallel,  then  join  results    def  call_maps(map_func)        results  =  []        nodes  =  @ring.nodes  -­‐  [@name]        nodes.map  {|node|            Thread.new  do                res  =  remote_call(node,  "map  #{map_func}")                results  +=  eval(res)            end        }.each{|w|  w.join}        results  +=  Map.new(map_func,  @data).call    end end Monday, April 22, 13
  • 42. 200.times  do  |i|    req.send(  "put  2  key#{i}  {}  #{i}"  )  &&  req.recv end req.send(  "mr  map{|k,v|  [1]};  reduce{|vs|  vs.length}"  ) puts  req.recv Monday, April 22, 13
  • 43. 200.times  do  |i|    req.send(  "put  2  key#{i}  {}  #{i}"  )  &&  req.recv end req.send(  "mr  map{|k,v|  [1]};  reduce{|vs|  vs.length}"  ) puts  req.recv Monday, April 22, 13
  • 45. WHAT WE’VE DONE SO FAR http://git.io/MYrjpQ • Distributed, Replicated, Self-healing, Conflict-resolving, Eventually Consistent Key/Value Datastore... with Mapreduce Monday, April 22, 13
  • 46. Key/Value Preference List Vector Clocks Distributed Hash Ring Request/ Response Merkle Tree Node Gossip CRDT (coming) Read Repair Monday, April 22, 13
  • 47. basho @coderoshi http://pragprog.com/book/rwdata http://github.com/coderoshi/little_riak_book Monday, April 22, 13
  • 48. I am the very model of a distributed database, I've information in my nodes residing out in cyber space, While other datastorers keep consistent values just in case, It's tolerant partitions and high uptime, that I embrace. Monday, April 22, 13
  • 49. I use a SHA-1algorithm, one-sixty bits of hashing space consistent hash ensures k/v's are never ever out of place, I replicate my data across more than one partition, In case a running node or two encounters decommission. Monday, April 22, 13
  • 50. My read repairs consistently, at least it does eventually, CAP demands you've only 2 to choose from preferentially, In short, you get consistency or high availability, To claim you can distribute and do both is pure futility. Monday, April 22, 13
  • 51. A system such as I is in a steady tiff with Entropy, since practically a quorum is consistent only sloppily, My favorite solutions are both read repair and AAE, My active anti-entropy trades deltas via Merkel Tree. Monday, April 22, 13
  • 52. After write, the clients choose their conflict resolution, With convergent replicated data types are a solution: I only take a change in state, and not results imperforate, And merge results to forge a final value that is proximate. Monday, April 22, 13
  • 53. How to know a sequence of events w/o employing locks, Well naturally, I use Lamport logic ordered vector-clocks. I have both sibling values when my v-clocks face a conflict, and keep successive values 'til a single one is picked. Monday, April 22, 13
  • 54. If values are your query goal then write some mapreduces. Invert-indexing values may reduce query obtuseness. Distributing a graph or a relation-style structure, though somewhat possible provides a weaker juncture. Monday, April 22, 13
  • 55. For data of the meta kind, my ring state is a toss up, To keep in sync my nodes will chat through protocol gossip. I am a mesh type network, not tree/star topological, their single points of failure make such choices most illogical. Monday, April 22, 13
  • 56. My network ring is just the thing, ensuring writes are quick, But know that CAP demands my choice give only 2 to pick. In short, I get consistency or high availability, To claim I could distribute and do both is just futility. Monday, April 22, 13