Document Locking
with Redis
Tom Corrigan
rostercloud.com
!

@thetommygnr

Melbourne PHP Users Group
November 2013
•

Cloud hosted SaaS product

•

Provide staff rostering primarily for hospitality companies

•

Focus on rostering staff ...
The problem
•

Multiple users editing an event at the same time

•

Resulting in:
•

Lost work

•

Unhappy customers
Solutions
•

Do nothing, let our customers figure it out
•

•

we might not have any customers

Store locks in our mysql da...
Redis - A better way

Redis is an open source, BSD licensed, advanced
key-value store. It is often referred to as a data
s...
Redis…
•

Developed by Salvatore Sanfilippo (@antirez)

•

An in-memory data store with optional disk persistence

•

Clust...
Using Redis
•

predis is the de facto standard library for PHP

•

can be further accelerated with a C extension

•

As a ...
How did we do it?

•

Create a set using the event id to form a key name

•

Populate the set with the ids of users who ha...
Edit action
<?php	
class EventController extends Controller {	
!

	
	

public function editAction($event){	
	 //...	

!

	...
Releasing a lock
public function updateAction(Request $request, $id)	
{	
	 //$businessLogic->doStuff($event)	
	 //etc...	
...
Maintaining a lock while editing
Client Side
!

function pollEditLock() {	
	 	 $.get(	
	 	 	 '{{ path(‘event_edit_lock’,	
...
Sometimes users want to edit concurrently
public function editConflictAction(Request $request, $id)	
{	
	 //...	
!
	 $redi...
Thankyou
Further Reading:
•

http://redis.io/

•

Slides available at https://speakerdeck.com/u/
tommygnr or from http://p...
Upcoming SlideShare
Loading in …5
×

Document Locking with Redis in Symfony2

3,504 views

Published on

A demonstration of an approach we used to disallow concurrent editing of records in our application. We used Redis, symfony2 and Doctrine2

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,504
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
14
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Document Locking with Redis in Symfony2

  1. 1. Document Locking with Redis Tom Corrigan rostercloud.com ! @thetommygnr Melbourne PHP Users Group November 2013
  2. 2. • Cloud hosted SaaS product • Provide staff rostering primarily for hospitality companies • Focus on rostering staff to ad hoc events, not regular schedules • 3 founders - I’m the IT guy
  3. 3. The problem • Multiple users editing an event at the same time • Resulting in: • Lost work • Unhappy customers
  4. 4. Solutions • Do nothing, let our customers figure it out • • we might not have any customers Store locks in our mysql database • edge cases are ugly
  5. 5. Redis - A better way Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.
  6. 6. Redis… • Developed by Salvatore Sanfilippo (@antirez) • An in-memory data store with optional disk persistence • Clusters easily • Documentation is amazing! • Has myriad uses beyond what I am discussing today • Take a look, it will open your eyes to new solutions to age old problems
  7. 7. Using Redis • predis is the de facto standard library for PHP • can be further accelerated with a C extension • As a key value store Redis has a very simple command set • We will be focusing on a handful of commands today
  8. 8. How did we do it? • Create a set using the event id to form a key name • Populate the set with the ids of users who have opened a read lock
  9. 9. Edit action <?php class EventController extends Controller { ! public function editAction($event){ //... ! //Check for an existing lock and redirect if one exists $redisKey = 'event_edit_'.$event->getId(); $redis = $this->container->get('snc_redis.default'); if ($redis->exists($redisKey)) { if (!$redis->sismember($redisKey, $this->getUser()->getId())){ return $this->redirect($this->generateUrl(‘event_edit_conflict’, array('id' => $id))); } } //Create a lock for this user $redis->sadd($redisKey, $this->getUser()->getId()); $redis->expire($redisKey, 120); } //...
  10. 10. Releasing a lock public function updateAction(Request $request, $id) { //$businessLogic->doStuff($event) //etc... ! //Once the changes have been flushed to the database release the lock $redis = $this->container->get('snc_redis.default'); $redis->srem('event_edit_'.$event->getId(), $this->getUser()->getId()); ! //... }
  11. 11. Maintaining a lock while editing Client Side ! function pollEditLock() { $.get( '{{ path(‘event_edit_lock’, { 'id': entity.id })}}’, function(data) { //Do something } ); } ! setInterval(pollEditLock, 30 * 1000); ! Server Side ! <?php //... public function editLockAction(Event $event) { //... $redisKey = 'event_edit_'.$event->getId(); $redis = $this->container->get('snc_redis.default'); ! $redis->sadd($redisKey, $this->getUser()->getId()); $redis->expire($redisKey, self::LOCK_TIME); ! return new JsonResponse(array('ok')); } //...
  12. 12. Sometimes users want to edit concurrently public function editConflictAction(Request $request, $id) { //... ! $redisKey = 'event_edit_'.$entity->getId(); $redis = $this->container->get('snc_redis.default'); ! if ($request->query->get('force')) { $redis->sadd($redisKey, $this->getUser()->getId()); $redis->expire($redisKey, self::LOCK_TIME); ! return $this->redirect($this->generateUrl('event_edit', array('id' => $id))); } $users = array(); $client = $this->get('context.client'); foreach ($redis->smembers($redisKey) as $userId){ $users[] = $em->getRepository(‚ÀòRCRosterBundle:User‚ÀÙ)->find($userId); } ! //... }
  13. 13. Thankyou Further Reading: • http://redis.io/ • Slides available at https://speakerdeck.com/u/ tommygnr or from http://phpmelb.org

×