35. Redis - Distributed Coordination
Redis is single threaded. That can be used to solve
coordination problems across machines.
36. Redis - Distributed Coordination
Redis is single threaded. That can be used to solve
coordination problems across machines.
Can we build a distributed lock with Redis?
37. Redis - Distributed Coordination
Redis is single threaded. That can be used to solve
coordination problems across machines.
Can we build a distributed lock with Redis?
Possible solution:
• Single key: ‘lock’
• 0: unlocked
• 1: locked
38. Redis - Distributed Coordination
class Lock(object):
"""
A shared, distributed Lock. Using Redis for locking allows the Lock
to be shared across processes and/or machines.
It's left to the user to resolve deadlock issues and make sure
multiple clients play nicely together.
"""
39. A deeper look into Lock
class Lock(object):
…
LUA_RELEASE_SCRIPT = """
local token = redis.call('get', KEYS[1])
if not token or token ~= ARGV[1] then
return 0
end
redis.call('del', KEYS[1])
return 1
"""
…
LUA_REACQUIRE_SCRIPT = """
…
47. Lua Scripts >> Transactions
“…everything you can do with a Redis transaction,
you can also do with a script, and usually the script
will be both simpler and faster.”
- https://redis.io/topics/transactions
48. Increment Lua Script
—- Increments number of treats
local num_treats = redis.call('get', 'treats')
num_treats = num_treats + 1
return redis.call('set', 'treats', num_treats)
49. How Lua Scripts solve Distributed Problems
…
CONTROLLER
Parameters
50. Lua Scripts - Leader Election
• Problem: Multiple identical nodes. Who is the leader?
• Requirement: All nodes must agree on one leader
51. Lua Scripts - Leader Election
• Problem: Multiple identical nodes. Who is the leader?
• Requirement: All nodes must agree on one leader
• Possible solution: “leader” and “members” keys.
52. Lua Scripts - Leader Election
local node_id = …
local leader_exists = redis.call('exists', 'leader')
if leader_exists then
redis.call('sadd', 'members', node_id)
return 0
else
redis.call('set', 'leader', node_id)
return 1
end
54. Lua Scripts - Load Balancer
• Problem: How do we assign subcontrollers to rollouts?
• Requirement: The load should be evenly split
55. Lua Scripts - Load Balancer
• Problem: How do we assign subcontrollers to rollouts?
• Requirement: The load should be evenly split
• Possible solution: Sorted set for number of connected rollouts
56. Lua Scripts - Load Balancer
-- subcontrollers sorted set key
local zkey = …
-- zrange returns a sorted array from lowest score to highest
local subcontroller = redis.call('zrange', zkey, 0, 0)[1]
-- Increment the count of the subcontroller
redis.call('zincrby', zkey, 1, subcontroller)
return subcontroller
57. Why Lua Scripts are amazing
• Better version of Transactions
• Execute arbitrary logic in the Redis itself
• Multiple inputs
• Multiple outputs
61. Simulations: Why is the setup time so high?
All configs are in Controller Redis
Any new instance must pull its job from it.
Crash loop nightmare:
• Instance wakes up, asks for config
• Timeout
• Crash
• Instance restarts, asks for config