• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Document Locking with Redis in Symfony2
 

Document Locking with Redis in Symfony2

on

  • 1,836 views

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

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

Statistics

Views

Total Views
1,836
Views on SlideShare
1,836
Embed Views
0

Actions

Likes
1
Downloads
7
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Document Locking with Redis in Symfony2 Document Locking with Redis in Symfony2 Presentation Transcript

    • 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 to ad hoc events, not regular schedules • 3 founders - I’m the IT guy
    • 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 database • edge cases are ugly
    • 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.
    • 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
    • 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
    • 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
    • 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); } //...
    • 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()); ! //... }
    • 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')); } //...
    • 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); } ! //... }
    • Thankyou Further Reading: • http://redis.io/ • Slides available at https://speakerdeck.com/u/ tommygnr or from http://phpmelb.org