SlideShare a Scribd company logo
1 of 89
Download to read offline
DEVELOPING POLYGLOT
  PERSISTENCE APPLICATIONS
Chris Richardson
Author of POJOs in Action
Founder of the original CloudFoundry.com
    @crichardson chris.richardson@springsource.com
http://plainoldobjects.com
Presentation goal
The benefits and drawbacks of
     polyglot persistence
             and
How to design applications that
     use this approach
                            @crichardson
About Chris




              @crichardson
(About Chris)




                @crichardson
About Chris()




                @crichardson
About Chris




              @crichardson
About Chris




http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/




                                                                      @crichardson
vmc push About-Chris


    Developer Advocate for
      CloudFoundry.com

Signup at http://cloudfoundry.com


                              @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
Food to Go



• Take-out   food delivery
 service

• “Launched” in   2006




                                   @crichardson
Food To Go Architecture
                              RESTAURANT
        CONSUMER
                                OWNER


   Order                Restaurant
   taking              Management



            MySQL
            Database

                                     @crichardson
Success                  Growth challenges


• Increasing   traffic

• Increasing   data volume

• Distribute   across a few data centers

• Increasing   domain model complexity


                                            @crichardson
Limitations of relational
                    databases

• Scalability

• Distribution

• Schema   updates

• O/R   impedance mismatch

• Handling   semi-structured data

                                         @crichardson
Solution: Spend Money



http://upload.wikimedia.org/wikipedia/commons/e/e5/Rising_Sun_Yacht.JPG

                                                                                   OR



                                                                          http://www.trekbikes.com/us/en/bikes/road/race_performance/madone_5_series/madone_5_2/#



                                                                                                                                           @crichardson
Solution: Use NoSQL
    Benefits                  Drawbacks

•   Higher performance   •   Limited transactions

•   Higher scalability   •   Limited querying

•   Richer data-model    •   Relaxed consistency

•   Schema-less          •   Unconstrained data



                                                    @crichardson
Example NoSQL Databases
Database                             Key features

Cassandra        Extensible column store, very scalable, distributed

Neo4j            Graph database
                 Document-oriented, fast, scalable
MongoDB

Redis            Key-value store, very fast

           http://nosql-database.org/ lists 122+ NoSQL
                             databases               @crichardson
Redis
• Advanced    key-value store                       K1    V1

• C-based    server
                                                    K2    V2
• Very   fast, e.g. 100K reqs/sec
                                                    ...   ...
• Optional   persistence

• Transactions   with optimistic locking

• Master-slave   replication

• Sharding   using client-side consistent hashing
                                                           @crichardson
Sorted sets
                                 Value
       Key

                            a       b
                   myset
                           5.0     10.




 Members are               Score
sorted by score


                                         @crichardson
Adding members to a sorted set
                            Redis Server

   Key    Score     Value

                                            a
 zadd myset 5.0 a             myset
                                           5.0




                                                 @crichardson
Adding members to a sorted set
                     Redis Server




                                     a     b
 zadd myset 10.0 b     myset
                                    5.0   10.




                                          @crichardson
Adding members to a sorted set
                    Redis Server




                               c     a     b
 zadd myset 1.0 c     myset
                              1.0   5.0   10.




                                     @crichardson
Retrieving members by index range
              Start        End
      Key
             Index        Index   Redis Server


    zrange myset 0 1

                                             c     a     b
                                    myset
                                            1.0   5.0   10.
              c       a




                                                   @crichardson
Retrieving members by score
                  Min        Max
          Key
                 value       value   Redis Server


zrangebyscore myset 1 6

                                                c     a     b
                                       myset
                                               1.0   5.0   10.
                   c     a




                                                      @crichardson
Redis use cases
•   Replacement for Memcached          •   Handling tasks that overload an RDBMS
    •   Session state                      •   Hit counts - INCR
    •   Cache of data retrieved from       •   Most recent N items - LPUSH and
        system of record (SOR)                 LTRIM
•   Replica of SOR for queries             •   Randomly selecting an item –
    needing high-performance                   SRANDMEMBER
                                           •   Queuing – Lists with LPOP, RPUSH, ….
                                           •   High score tables – Sorted sets and
                                               ZINCRBY
                                           •   …




                                                                           @crichardson
Redis is great but there are
                     tradeoffs
•   Low-level query language: PK-based access only

•   Limited transaction model:

    •   Read first and then execute updates as batch

    •   Difficult to compose code

•   Data must fit in memory

•   Single-threaded server: run multiple with client-side sharding

•   Missing features such as access control, ...
                                                                     @crichardson
And don’t forget:

An RDBMS is fine for many
      applications

                        @crichardson
The future is polyglot


                                                                        e.g. Netflix
                                                                        • RDBMS
                                                                        • SimpleDB
                                                                        • Cassandra
                                                                        • Hadoop/Hbase




IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg




                                                                                   @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
Food to Go – Domain model (partial)
class Restaurant {                   class TimeRange {
  long id;                             long id;
  String name;                         int dayOfWeek;
  Set<String> serviceArea;             int openTime;
  Set<TimeRange> openingHours;         int closeTime;
  List<MenuItem> menuItems;
                                     }
}


                  class MenuItem {
                    String name;
                    double price;
                  }

                                                @crichardson
Database schema
ID                Name                           …
                                                                   RESTAURANT table
1                 Ajanta
2                 Montclair Eggshop

Restaurant_id             zipcode
                                                      RESTAURANT_ZIPCODE table
1                         94707
1                         94619
2                         94611
2                         94619
                                                     RESTAURANT_TIME_RANGE table
Restaurant_id   dayOfWeek             openTime         closeTime
1               Monday                1130             1430
1               Monday                1730             2130
2               Tuesday               1130             …



                                                                         @crichardson
RestaurantRepository

  public interface RestaurantRepository {
    void addRestaurant(Restaurant restaurant);
    Restaurant findById(long id);
    ...
  }



Food To Go will have scaling
      eventually issues
                                                 @crichardson
Increase scalability by caching
                            RESTAURANT
          CONSUMER
                              OWNER


     Order            Restaurant
     taking          Management



                 MySQL
         Cache
                 Database
                                   @crichardson
Caching Options
•   Where:

    •   Hibernate 2nd level cache

    •   Explicit calls from application code

    •   Caching aspect

•   Cache technologies: Ehcache, Memcached, Infinispan, ...



                Redis is also an option
                                                             @crichardson
Using Redis as a cache
•   Spring 3.1 cache abstraction

    •   Annotations specify which methods to cache

    •   CacheManager - pluggable back-end cache

•   Spring Data for Redis

    •   Simplifies the development of Redis applications

    •   Provides RedisTemplate (analogous to JdbcTemplate)

    •   Provides RedisCacheManager
                                                             @crichardson
Using Spring 3.1 Caching
@Service
public class RestaurantManagementServiceImpl implements RestaurantManagementService {

  private final RestaurantRepository restaurantRepository;

  @Autowired
  public RestaurantManagementServiceImpl(RestaurantRepository restaurantRepository) {
    this.restaurantRepository = restaurantRepository;
  }

  @Override
  public void add(Restaurant restaurant) {
                                                                 Cache result
    restaurantRepository.add(restaurant);
  }

  @Override
  @Cacheable(value = "Restaurant")
  public Restaurant findById(int id) {
    return restaurantRepository.findRestaurant(id);
                                                                    Evict from
  }                                                                   cache
  @Override
  @CacheEvict(value = "Restaurant", key="#restaurant.id")
  public void update(Restaurant restaurant) {
    restaurantRepository.update(restaurant);
  }


                                                                                        @crichardson
Configuring the Redis Cache
              Manager
         Enables caching


	   <cache:annotation-driven />

	   <bean id="cacheManager"
          class="org.springframework.data.redis.cache.RedisCacheManager" >
	   	 <constructor-arg ref="restaurantTemplate"/>
	   </bean>




    Specifies CacheManager                  The RedisTemplate used
        implementation                         to access Redis
                                                                   @crichardson
Domain object to key-value
          mapping?

      Restaurant
                         K1    V1


TimeRange
TimeRange     MenuItem
              MenuItem   K2    V2

                         ...   ...
     ServiceArea


                               @crichardson
RedisTemplate handles the
               mapping

• Principal API   provided by Spring Data to Redis

• Analogous   to JdbcTemplate

• Encapsulates    boilerplate code, e.g. connection management

• Maps   Java objects          Redis byte[]’s


                                                          @crichardson
Serializers: object                       byte[]

• RedisTemplate     has multiple serializers

• DefaultSerializer   - defaults to JdkSerializationRedisSerializer

• KeySerializer

• ValueSerializer

• HashKeySerializer

• HashValueSerializer

                                                                @crichardson
Serializing a Restaurant as JSON
@Configuration
public class RestaurantManagementRedisConfiguration {

    @Autowired
    private RestaurantObjectMapperFactory restaurantObjectMapperFactory;

    private JacksonJsonRedisSerializer<Restaurant> makeRestaurantJsonSerializer() {
      JacksonJsonRedisSerializer<Restaurant> serializer =
                           new JacksonJsonRedisSerializer<Restaurant>(Restaurant.class);
      ...
      return serializer;
    }

    @Bean
    @Qualifier("Restaurant")
    public RedisTemplate<String, Restaurant> restaurantTemplate(RedisConnectionFactory factory) {
      RedisTemplate<String, Restaurant> template = new RedisTemplate<String, Restaurant>();
      template.setConnectionFactory(factory);
      JacksonJsonRedisSerializer<Restaurant> jsonSerializer = makeRestaurantJsonSerializer();
      template.setValueSerializer(jsonSerializer);
      return template;
    }
                                                    Serialize restaurants using Jackson
}                                                                  JSON
                                                                                           @crichardson
Caching with Redis
                               RESTAURANT
             CONSUMER
                                 OWNER


        Order            Restaurant
        taking          Management



            Redis   MySQL
First                                 Second
            Cache   Database
                                         @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
Finding available restaurants
Available restaurants =
   Serve the zip code of the delivery address
                                  AND
   Are open at the delivery time

public interface AvailableRestaurantRepository {

   List<AvailableRestaurant>
	

 findAvailableRestaurants(Address deliveryAddress, Date deliveryTime);
   ...
}
                                                                 @crichardson
Finding available restaurants on Monday, 6.15pm
                 for 94619 zipcode
                      Straightforward three-way join

select r.*
from restaurant r
 inner join restaurant_time_range tr
   on r.id =tr.restaurant_id
 inner join restaurant_zipcode sa
   on r.id = sa.restaurant_id
where ’94619’ = sa.zip_code
 and tr.day_of_week=’monday’
 and tr.openingtime <= 1815
 and 1815 <= tr.closingtime

                                                       @crichardson
How to scale queries?



                        @crichardson
Option #1: Query caching


• [ZipCode, DeliveryTime]   ⇨ list of available restaurants

                              BUT

• Long   tail queries

• Update   restaurant ⇨ Flush entire cache

                   Ineffective
                                                              @crichardson
Option #2: Master/Slave replication
                  Writes    Consistent reads



                                               Queries
                           MySQL
                                         (Inconsistent reads)
                           Master




        MySQL              MySQL               MySQL
        Slave 1            Slave 2             Slave N



                                                            @crichardson
Master/Slave replication

• Mostly   straightforward

                                BUT

• Assumes    that SQL query is efficient

• Complexity    of administration of slaves

• Doesn’t   scale writes

                                              @crichardson
Option #3: Redis materialized
             views
                                          RESTAURANT
                  CONSUMER
                                            OWNER


            Order                   Restaurant
            taking                 Management       System
                                                    of
Copy                    update()                    Record
       findAvailable()
                                         MySQL
          Redis              Cache
                                         Database
                                                    @crichardson
BUT how to implement findAvailableRestaurants()
                with Redis?!



                                       ?
select r.*
from restaurant r                          K1    V1
 inner join restaurant_time_range tr
   on r.id =tr.restaurant_id
 inner join restaurant_zipcode sa
   on r.id = sa.restaurant_id
                                           K2    V2
where ’94619’ = sa.zip_code
 and tr.day_of_week=’monday’
 and tr.openingtime <= 1815                ...   ...
 and 1815 <= tr.closingtime




                                                 @crichardson
Solution: Build an index using sorted
   sets and ZRANGEBYSCORE
ZRANGEBYSCORE myset 1 6

           =
                          sorted_set
select value               key value score
from sorted_set
where key = ‘myset’
  and score >= 1
  and score <= 6

                                    @crichardson
How to transform the SELECT
            statement?

select r.*
from restaurant r
 inner join restaurant_time_range tr
   on r.id =tr.restaurant_id
 inner join restaurant_zipcode sa
                                       ?   select value
                                           from sorted_set
                                           where key = ?
   on r.id = sa.restaurant_id                and score >= ?
where ’94619’ = sa.zip_code                  and score <= ?
  and tr.day_of_week=’monday’
  and tr.openingtime <= 1815
  and 1815 <= tr.closingtime




                                                          @crichardson
We need to denormalize


Think materialized view

                          @crichardson
Simplification #1:
                     Denormalization
Restaurant_id   Day_of_week   Open_time   Close_time        Zip_code

1               Monday        1130        1430              94707
1               Monday        1130        1430              94619
1               Monday        1730        2130              94707
1               Monday        1730        2130              94619
2               Monday        0700        1430              94619
…



           SELECT restaurant_id
           FROM time_range_zip_code
           WHERE day_of_week = ‘Monday’                Simpler query:
                                                        No joins
             AND zip_code = 94619                       Two = and two <
             AND 1815 < close_time
             AND open_time < 1815
                                                                       @crichardson
Simplification #2: Application
             filtering
SELECT restaurant_id, open_time
FROM time_range_zip_code
WHERE day_of_week = ‘Monday’      Even simpler query
                                  • No joins
  AND zip_code = 94619
                                  • Two = and one <
  AND 1815 < close_time
  AND open_time < 1815




                                                       @crichardson
Simplification #3: Eliminate multiple =’s with
                 concatenation
 Restaurant_id   Zip_dow        Open_time   Close_time

 1               94707:Monday   1130        1430
 1               94619:Monday   1130        1430
 1               94707:Monday   1730        2130
 1               94619:Monday   1730        2130
 2               94619:Monday   0700        1430
 …


SELECT restaurant_id, open_time
FROM time_range_zip_code
WHERE zip_code_day_of_week = ‘94619:Monday’
  AND 1815 < close_time
                                                         key
                                range

                                                               @crichardson
Simplification #4: Eliminate multiple RETURN
        VALUES with concatenation
   zip_dow         open_time_restaurant_id   close_time
   94707:Monday    1130_1                    1430
   94619:Monday    1130_1                    1430
   94707:Monday    1730_1                    2130
   94619:Monday    1730_1                    2130
   94619:Monday    0700_2                    1430
   ...




  SELECT open_time_restaurant_id,
  FROM time_range_zip_code
  WHERE zip_code_day_of_week = ‘94619:Monday’
    AND 1815 < close_time
                                                          ✔
                                                          @crichardson
Using a Redis sorted set as an index
        zip_dow        open_time_restaurant_id       close_time
        94707:Monday   1130_1                        1430
        94619:Monday   1130_1                        1430
        94707:Monday   1730_1                        2130
        94619:Monday   1730_1                        2130
        94619:Monday   0700_2                        1430
        ...




  Key                     Sorted Set [ Entry:Score, …]

  94619:Monday            [0700_2:1430, 1130_1:1430, 1730_1:2130]

  94707:Monday            [1130_1:1430, 1730_1:2130]



                                                                    @crichardson
Querying with ZRANGEBYSCORE
 Key                           Sorted Set [ Entry:Score, …]

 94619:Monday                  [0700_2:1430, 1130_1:1430, 1730_1:2130]

 94707:Monday                  [1130_1:1430, 1730_1:2130]



                     Delivery zip and day                Delivery time


                ZRANGEBYSCORE 94619:Monday 1815 2359
                                
                             {1730_1}



                 1730 is before 1815  Ajanta is open


                                                                         @crichardson
Adding a Restaurant
@Component
public class AvailableRestaurantRepositoryImpl implements AvailableRestaurantRepository {

  @Override
  public void add(Restaurant restaurant) {
    addRestaurantDetails(restaurant);
                                                                 Store as
    addAvailabilityIndexEntries(restaurant);                      JSON
  }

                                               Text
  private void addRestaurantDetails(Restaurant restaurant) {
    restaurantTemplate.opsForValue().set(keyFormatter.key(restaurant.getId()), restaurant);
  }

  private void addAvailabilityIndexEntries(Restaurant restaurant) {
    for (TimeRange tr : restaurant.getOpeningHours()) {
      String indexValue = formatTrId(restaurant, tr);                  key          member
      int dayOfWeek = tr.getDayOfWeek();
      int closingTime = tr.getClosingTime();
      for (String zipCode : restaurant.getServiceArea()) {
        redisTemplate.opsForZSet().add(closingTimesKey(zipCode, dayOfWeek), indexValue,
                                       closingTime);
      }
    }
  }                                                            score
                                                                                      @crichardson
Finding available Restaurants
@Component
public class AvailableRestaurantRepositoryImpl implements AvailableRestaurantRepository {
  @Override
  public List<AvailableRestaurant>
       findAvailableRestaurants(Address deliveryAddress, Date deliveryTime) {       Find those that
    String zipCode = deliveryAddress.getZip();                                         close after
    int dayOfWeek = DateTimeUtil.dayOfWeek(deliveryTime);
    int timeOfDay = DateTimeUtil.timeOfDay(deliveryTime);
    String closingTimesKey = closingTimesKey(zipCode, dayOfWeek);

      Set<String> trsClosingAfter =
                redisTemplate.opsForZSet().rangeByScore(closingTimesKey, timeOfDay, 2359);

      Set<String> restaurantIds = new HashSet<String>();
      for (String tr : trsClosingAfter) {                                         Filter out those that
        String[] values = tr.split("_");                                                open after
        if (Integer.parseInt(values[0]) <= timeOfDay)
          restaurantIds.add(values[1]);
      }
      Collection<String> keys = keyFormatter.keys(restaurantIds);
      return availableRestaurantTemplate.opsForValue().multiGet(keys);                     Retrieve open
  }                                                                                         restaurants


                                                                                             @crichardson
Sorry Ted!




http://en.wikipedia.org/wiki/Edgar_F._Codd

                                             @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
MySQL & Redis
need to be consistent



                        @crichardson
Two-Phase commit is not an
              option


• Redis   does not support it

• Even    if it did, 2PC is best avoided   http://www.infoq.com/articles/ebay-scalability-best-practices




                                                                                                       @crichardson
Atomic
Consistent                               Basically Available
Isolated                                 Soft state
Durable                                  Eventually consistent




BASE: An Acid Alternative http://queue.acm.org/detail.cfm?id=1394128


                                                                       @crichardson
Updating Redis #FAIL
begin MySQL transaction
 update MySQL                Redis has update
 update Redis                MySQL does not
rollback MySQL transaction

begin MySQL transaction
 update MySQL
                             MySQL has update
commit MySQL transaction
                             Redis does not
<<system crashes>>
 update Redis


                                         @crichardson
Updating Redis reliably
        Step 1 of 2
begin MySQL transaction
 update MySQL
                                       ACID
 queue CRUD event in MySQL
commit transaction


   Event Id
   Operation: Create, Update, Delete
   New entity state, e.g. JSON

                                        @crichardson
Updating Redis reliably
           Step 2 of 2
for each CRUD event in MySQL queue
    get next CRUD event from MySQL queue
    If CRUD event is not duplicate then
     Update Redis (incl. eventId)
    end if
    begin MySQL transaction
      mark CRUD event as processed
    commit transaction

                                       @crichardson
Step 1               Step 2
                                      Timer
  EntityCrudEvent          EntityCrudEvent   apply(event)    Redis
    Repository                Processor                     Updater



INSERT INTO ...            SELECT ... FROM ...


      ENTITY_CRUD_EVENT


            ID            JSON     processed?
                                                            Redis


                                                               @crichardson
Optimistic
 locking                 Updating Redis

WATCH restaurant:lastSeenEventId:≪restaurantId≫

lastSeenEventId = GET restaurant:lastSeenEventId:≪restaurantId≫
                                                                   Duplicate
if (lastSeenEventId >= eventId) return;                            detection
MULTI
 SET restaurant:lastSeenEventId:≪restaurantId≫ eventId
                                                                  Transaction
  ... update the restaurant data...

EXEC




                                                                     @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
How do we generate CRUD
        events?



                      @crichardson
Change tracking options


• Explicit   code

• Hibernate    event listener

• Service-layer     aspect

• CQRS/Event-sourcing



                                       @crichardson
HibernateEvent              EntityCrudEvent
   Listener                   Repository




      ENTITY_CRUD_EVENT


            ID            JSON    processed?




                                               @crichardson
Hibernate event listener
public class ChangeTrackingListener
  implements PostInsertEventListener, PostDeleteEventListener, PostUpdateEventListener {

 @Autowired
 private EntityCrudEventRepository entityCrudEventRepository;

 private void maybeTrackChange(Object entity, EntityCrudEventType eventType) {
   if (isTrackedEntity(entity)) {
     entityCrudEventRepository.add(new EntityCrudEvent(eventType, entity));
   }
 }

 @Override
 public void onPostInsert(PostInsertEvent event) {
   Object entity = event.getEntity();
   maybeTrackChange(entity, EntityCrudEventType.CREATE);
 }

 @Override
 public void onPostUpdate(PostUpdateEvent event) {
   Object entity = event.getEntity();
   maybeTrackChange(entity, EntityCrudEventType.UPDATE);
 }

 @Override
 public void onPostDelete(PostDeleteEvent event) {
   Object entity = event.getEntity();
   maybeTrackChange(entity, EntityCrudEventType.DELETE);
 }

                                                                                           @crichardson
Agenda

• Why     polyglot persistence?

• Using   Redis as a cache

• Optimizing    queries using Redis materialized views

• Synchronizing   MySQL and Redis

• Tracking   changes to entities

• Using   a modular asynchronous architecture
                                                         @crichardson
Original architecture
     WAR
        Restaurant
       Management

           ...




                        @crichardson
Drawbacks of this monolithic
       architecture
               • Obstacle
                        to frequent
WAR
                deployments
  Restaurant
 Management    • Overloads   IDE and web
                container
      ...
               • Obstacle
                        to scaling
                development

               • Technology   lock-in

                                        @crichardson
Need a more modular
    architecture



                      @crichardson
Using a message broker

Asynchronous is preferred


JSON is fashionable but binary
   format is more efficient



                            @crichardson
Modular architecture
                                                 RESTAURANT
        CONSUMER              Timer
                                                   OWNER




 Order                 Event             Restaurant
 taking               Publisher         Management




                                      MySQL        Redis
Redis              RabbitMQ
                                      Database     Cache
                                                      @crichardson
Benefits of a modular
       asynchronous architecture
• Scales
       development: develop, deploy and scale each service
 independently

• Redeploy     UI frequently/independently

• Improves   fault isolation

• Eliminates   long-term commitment to a single technology stack

• Message   broker decouples producers and consumers

                                                          @crichardson
Step 2 of 2

for each CRUD event in MySQL queue
 get next CRUD event from MySQL queue
  Publish persistent message to RabbitMQ
  begin MySQL transaction
   mark CRUD event as processed
  commit transaction



                                     @crichardson
Message flow
EntityCrudEvent
   Processor
                             AvailableRestaurant
                             ManagementService
         Redis
        Updater


       Spring Integration glue code


                  RABBITMQ                    REDIS

                                                      @crichardson
RedisUpdater                             AMQP
<beans>
                                                        Creates proxy
	   <int:gateway id="redisUpdaterGateway"
     	 service-interface="net...RedisUpdater"
	   	 default-request-channel="eventChannel"
     	 />

	   <int:channel id="eventChannel"/>

	   <int:object-to-json-transformer
       input-channel="eventChannel" output-channel="amqpOut"/>

	   <int:channel id="amqpOut"/>

	   <amqp:outbound-channel-adapter
	   	 channel="amqpOut"
	   	 amqp-template="rabbitTemplate"
	   	 routing-key="crudEvents"
	   	 exchange-name="crudEvents"
	    />

</beans>                                                                @crichardson
AMQP                    Available...Service
<beans>
	 <amqp:inbound-channel-adapter
	 	 channel="inboundJsonEventsChannel"
	 	 connection-factory="rabbitConnectionFactory"
	 	 queue-names="crudEvents"/>

	 <int:channel id="inboundJsonEventsChannel"/>
	
	 <int:json-to-object-transformer
	 	 input-channel="inboundJsonEventsChannel"
	 	 type="net.chrisrichardson.foodToGo.common.JsonEntityCrudEvent"
	 	 output-channel="inboundEventsChannel"/>
	
	 <int:channel id="inboundEventsChannel"/>         Invokes service
	
	 <int:service-activator
	 	 input-channel="inboundEventsChannel"
	 	 ref="availableRestaurantManagementServiceImpl"
	 	 method="processEvent"/>
</beans>
                                                                     @crichardson
Summary

• Each   SQL/NoSQL database = set of tradeoffs

• Polyglot
       persistence: leverage the strengths of SQL and
 NoSQL databases

• Use   Redis as a distributed cache

• Store   denormalized data in Redis for fast querying

• Reliable   database synchronization required

                                                         @crichardson
@crichardson chris.richardson@springsource.com
  http://plainoldobjects.com - code and slides




 Sign up for CloudFoundry.com@crichardson

More Related Content

What's hot

Polyglot Persistence - Two Great Tastes That Taste Great Together
Polyglot Persistence - Two Great Tastes That Taste Great TogetherPolyglot Persistence - Two Great Tastes That Taste Great Together
Polyglot Persistence - Two Great Tastes That Taste Great TogetherJohn Wood
 
The Rise of NoSQL and Polyglot Persistence
The Rise of NoSQL and Polyglot PersistenceThe Rise of NoSQL and Polyglot Persistence
The Rise of NoSQL and Polyglot PersistenceAbdelmonaim Remani
 
MongoDB at eBay
MongoDB at eBayMongoDB at eBay
MongoDB at eBayMongoDB
 
2011 05-12 nosql-progressive.net
2011 05-12 nosql-progressive.net2011 05-12 nosql-progressive.net
2011 05-12 nosql-progressive.netMårten Gustafson
 
Apache Cassandra Certification
Apache Cassandra CertificationApache Cassandra Certification
Apache Cassandra CertificationVskills
 
Using Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterUsing Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterMongoDB
 
Webinar: Migrating from RDBMS to MongoDB
Webinar: Migrating from RDBMS to MongoDBWebinar: Migrating from RDBMS to MongoDB
Webinar: Migrating from RDBMS to MongoDBMongoDB
 
2011 03-31 Riak Stockholm Meetup
2011 03-31 Riak Stockholm Meetup2011 03-31 Riak Stockholm Meetup
2011 03-31 Riak Stockholm MeetupMårten Gustafson
 
2011 05-12 nosql-fritidsresor
2011 05-12 nosql-fritidsresor2011 05-12 nosql-fritidsresor
2011 05-12 nosql-fritidsresorMårten Gustafson
 
Storage Infrastructure Behind Facebook Messages
Storage Infrastructure Behind Facebook MessagesStorage Infrastructure Behind Facebook Messages
Storage Infrastructure Behind Facebook Messagesyarapavan
 
Conference tutorial: MySQL Cluster as NoSQL
Conference tutorial: MySQL Cluster as NoSQLConference tutorial: MySQL Cluster as NoSQL
Conference tutorial: MySQL Cluster as NoSQLSeveralnines
 
2010-11-12 Databases overview
2010-11-12 Databases overview2010-11-12 Databases overview
2010-11-12 Databases overviewMårten Gustafson
 
Omid: Efficient Transaction Management and Incremental Processing for HBase (...
Omid: Efficient Transaction Management and Incremental Processing for HBase (...Omid: Efficient Transaction Management and Incremental Processing for HBase (...
Omid: Efficient Transaction Management and Incremental Processing for HBase (...Daniel Gómez Ferro
 
Hadoop Summit 2012 | HBase Consistency and Performance Improvements
Hadoop Summit 2012 | HBase Consistency and Performance ImprovementsHadoop Summit 2012 | HBase Consistency and Performance Improvements
Hadoop Summit 2012 | HBase Consistency and Performance ImprovementsCloudera, Inc.
 
Qcon 090408233824-phpapp01
Qcon 090408233824-phpapp01Qcon 090408233824-phpapp01
Qcon 090408233824-phpapp01jgregory1234
 
Scalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsScalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsJonas Bonér
 
Branf final bringing mongodb into your organization - mongo db-boston2012
Branf final   bringing mongodb into your organization - mongo db-boston2012Branf final   bringing mongodb into your organization - mongo db-boston2012
Branf final bringing mongodb into your organization - mongo db-boston2012MongoDB
 

What's hot (20)

Polyglot Persistence - Two Great Tastes That Taste Great Together
Polyglot Persistence - Two Great Tastes That Taste Great TogetherPolyglot Persistence - Two Great Tastes That Taste Great Together
Polyglot Persistence - Two Great Tastes That Taste Great Together
 
The Rise of NoSQL and Polyglot Persistence
The Rise of NoSQL and Polyglot PersistenceThe Rise of NoSQL and Polyglot Persistence
The Rise of NoSQL and Polyglot Persistence
 
MongoDB at eBay
MongoDB at eBayMongoDB at eBay
MongoDB at eBay
 
2011 05-12 nosql-progressive.net
2011 05-12 nosql-progressive.net2011 05-12 nosql-progressive.net
2011 05-12 nosql-progressive.net
 
Apache Cassandra Certification
Apache Cassandra CertificationApache Cassandra Certification
Apache Cassandra Certification
 
Using Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterUsing Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your Cluster
 
Hadoop security
Hadoop securityHadoop security
Hadoop security
 
Webinar: Migrating from RDBMS to MongoDB
Webinar: Migrating from RDBMS to MongoDBWebinar: Migrating from RDBMS to MongoDB
Webinar: Migrating from RDBMS to MongoDB
 
2011 03-31 Riak Stockholm Meetup
2011 03-31 Riak Stockholm Meetup2011 03-31 Riak Stockholm Meetup
2011 03-31 Riak Stockholm Meetup
 
2011 05-12 nosql-fritidsresor
2011 05-12 nosql-fritidsresor2011 05-12 nosql-fritidsresor
2011 05-12 nosql-fritidsresor
 
Storage Infrastructure Behind Facebook Messages
Storage Infrastructure Behind Facebook MessagesStorage Infrastructure Behind Facebook Messages
Storage Infrastructure Behind Facebook Messages
 
NoSQL @ Qbranch -2010-04-15
NoSQL @ Qbranch -2010-04-15NoSQL @ Qbranch -2010-04-15
NoSQL @ Qbranch -2010-04-15
 
Conference tutorial: MySQL Cluster as NoSQL
Conference tutorial: MySQL Cluster as NoSQLConference tutorial: MySQL Cluster as NoSQL
Conference tutorial: MySQL Cluster as NoSQL
 
2010-11-12 Databases overview
2010-11-12 Databases overview2010-11-12 Databases overview
2010-11-12 Databases overview
 
Omid: Efficient Transaction Management and Incremental Processing for HBase (...
Omid: Efficient Transaction Management and Incremental Processing for HBase (...Omid: Efficient Transaction Management and Incremental Processing for HBase (...
Omid: Efficient Transaction Management and Incremental Processing for HBase (...
 
Hadoop Summit 2012 | HBase Consistency and Performance Improvements
Hadoop Summit 2012 | HBase Consistency and Performance ImprovementsHadoop Summit 2012 | HBase Consistency and Performance Improvements
Hadoop Summit 2012 | HBase Consistency and Performance Improvements
 
Qcon 090408233824-phpapp01
Qcon 090408233824-phpapp01Qcon 090408233824-phpapp01
Qcon 090408233824-phpapp01
 
Qcon
QconQcon
Qcon
 
Scalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsScalability, Availability & Stability Patterns
Scalability, Availability & Stability Patterns
 
Branf final bringing mongodb into your organization - mongo db-boston2012
Branf final   bringing mongodb into your organization - mongo db-boston2012Branf final   bringing mongodb into your organization - mongo db-boston2012
Branf final bringing mongodb into your organization - mongo db-boston2012
 

Viewers also liked

Decomposing applications for deployability and scalability (SpringOne China 2...
Decomposing applications for deployability and scalability (SpringOne China 2...Decomposing applications for deployability and scalability (SpringOne China 2...
Decomposing applications for deployability and scalability (SpringOne China 2...Chris Richardson
 
Polygot persistence for Java Developers - August 2011 / @Oakjug
Polygot persistence for Java Developers - August 2011 / @OakjugPolygot persistence for Java Developers - August 2011 / @Oakjug
Polygot persistence for Java Developers - August 2011 / @OakjugChris Richardson
 
Decomposing applications for scalability and deployability - svcc sv_code_ca...
Decomposing applications for scalability and deployability  - svcc sv_code_ca...Decomposing applications for scalability and deployability  - svcc sv_code_ca...
Decomposing applications for scalability and deployability - svcc sv_code_ca...Chris Richardson
 
Decomposing applications for scalability and deployability (devnexus 2013)
Decomposing applications for scalability and deployability (devnexus 2013)Decomposing applications for scalability and deployability (devnexus 2013)
Decomposing applications for scalability and deployability (devnexus 2013)Chris Richardson
 
Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Chris Richardson
 
Developing polyglot persistence applications (gluecon 2013)
Developing polyglot persistence applications (gluecon 2013)Developing polyglot persistence applications (gluecon 2013)
Developing polyglot persistence applications (gluecon 2013)Chris Richardson
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)Chris Richardson
 
Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Chris Richardson
 
Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)Chris Richardson
 
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...Chris Richardson
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Chris Richardson
 

Viewers also liked (11)

Decomposing applications for deployability and scalability (SpringOne China 2...
Decomposing applications for deployability and scalability (SpringOne China 2...Decomposing applications for deployability and scalability (SpringOne China 2...
Decomposing applications for deployability and scalability (SpringOne China 2...
 
Polygot persistence for Java Developers - August 2011 / @Oakjug
Polygot persistence for Java Developers - August 2011 / @OakjugPolygot persistence for Java Developers - August 2011 / @Oakjug
Polygot persistence for Java Developers - August 2011 / @Oakjug
 
Decomposing applications for scalability and deployability - svcc sv_code_ca...
Decomposing applications for scalability and deployability  - svcc sv_code_ca...Decomposing applications for scalability and deployability  - svcc sv_code_ca...
Decomposing applications for scalability and deployability - svcc sv_code_ca...
 
Decomposing applications for scalability and deployability (devnexus 2013)
Decomposing applications for scalability and deployability (devnexus 2013)Decomposing applications for scalability and deployability (devnexus 2013)
Decomposing applications for scalability and deployability (devnexus 2013)
 
Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)
 
Developing polyglot persistence applications (gluecon 2013)
Developing polyglot persistence applications (gluecon 2013)Developing polyglot persistence applications (gluecon 2013)
Developing polyglot persistence applications (gluecon 2013)
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)
 
Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)
 
Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)
 
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...
Map, Flatmap and Reduce are Your New Best Friends: Simpler Collections, Concu...
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
 

Similar to Developing polyglot persistence applications (devnexus 2013)

Polyglot persistence for Java developers: time to move out of the relational ...
Polyglot persistence for Java developers: time to move out of the relational ...Polyglot persistence for Java developers: time to move out of the relational ...
Polyglot persistence for Java developers: time to move out of the relational ...Chris Richardson
 
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Redis Labs
 
Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)Chris Richardson
 
Non-Relational Databases at ACCU2011
Non-Relational Databases at ACCU2011Non-Relational Databases at ACCU2011
Non-Relational Databases at ACCU2011Gavin Heavyside
 
SQL, NoSQL, NewSQL? What's a developer to do?
SQL, NoSQL, NewSQL? What's a developer to do?SQL, NoSQL, NewSQL? What's a developer to do?
SQL, NoSQL, NewSQL? What's a developer to do?Chris Richardson
 
Navigating NoSQL in cloudy skies
Navigating NoSQL in cloudy skiesNavigating NoSQL in cloudy skies
Navigating NoSQL in cloudy skiesshnkr_rmchndrn
 
Azure reference architectures
Azure reference architecturesAzure reference architectures
Azure reference architecturesMasashi Narumoto
 
10 Ways to Scale with Redis - LA Redis Meetup 2019
10 Ways to Scale with Redis - LA Redis Meetup 201910 Ways to Scale with Redis - LA Redis Meetup 2019
10 Ways to Scale with Redis - LA Redis Meetup 2019Dave Nielsen
 
Getting started with MariaDB with Docker
Getting started with MariaDB with DockerGetting started with MariaDB with Docker
Getting started with MariaDB with DockerMariaDB plc
 
10 Ways to Scale Your Website Silicon Valley Code Camp 2019
10 Ways to Scale Your Website Silicon Valley Code Camp 201910 Ways to Scale Your Website Silicon Valley Code Camp 2019
10 Ways to Scale Your Website Silicon Valley Code Camp 2019Dave Nielsen
 
Secure Redis Cluster At Box: Vova Galchenko, Ravitej Sistla
Secure Redis Cluster At Box: Vova Galchenko, Ravitej SistlaSecure Redis Cluster At Box: Vova Galchenko, Ravitej Sistla
Secure Redis Cluster At Box: Vova Galchenko, Ravitej SistlaRedis Labs
 
Add Redis to Postgres to Make Your Microservices Go Boom!
Add Redis to Postgres to Make Your Microservices Go Boom!Add Redis to Postgres to Make Your Microservices Go Boom!
Add Redis to Postgres to Make Your Microservices Go Boom!Dave Nielsen
 
Scaing databases on the cloud
Scaing databases on the cloudScaing databases on the cloud
Scaing databases on the cloudImaginea
 
Scaling Databases On The Cloud
Scaling Databases On The CloudScaling Databases On The Cloud
Scaling Databases On The CloudImaginea
 
NoSql Databases and Polyglot Applications
NoSql Databases and Polyglot ApplicationsNoSql Databases and Polyglot Applications
NoSql Databases and Polyglot ApplicationsAgustin Magaña
 
Running database infrastructure on containers
Running database infrastructure on containersRunning database infrastructure on containers
Running database infrastructure on containersMariaDB plc
 
Introduction to NoSQL
Introduction to NoSQLIntroduction to NoSQL
Introduction to NoSQLYan Cui
 
What's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsWhat's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsRedis Labs
 
Making (Almost) Any Database Faster and Cheaper with Caching
Making (Almost) Any Database Faster and Cheaper with CachingMaking (Almost) Any Database Faster and Cheaper with Caching
Making (Almost) Any Database Faster and Cheaper with CachingAmazon Web Services
 

Similar to Developing polyglot persistence applications (devnexus 2013) (20)

Polyglot persistence for Java developers: time to move out of the relational ...
Polyglot persistence for Java developers: time to move out of the relational ...Polyglot persistence for Java developers: time to move out of the relational ...
Polyglot persistence for Java developers: time to move out of the relational ...
 
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
 
Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)
 
Non-Relational Databases at ACCU2011
Non-Relational Databases at ACCU2011Non-Relational Databases at ACCU2011
Non-Relational Databases at ACCU2011
 
SQL, NoSQL, NewSQL? What's a developer to do?
SQL, NoSQL, NewSQL? What's a developer to do?SQL, NoSQL, NewSQL? What's a developer to do?
SQL, NoSQL, NewSQL? What's a developer to do?
 
Navigating NoSQL in cloudy skies
Navigating NoSQL in cloudy skiesNavigating NoSQL in cloudy skies
Navigating NoSQL in cloudy skies
 
Azure reference architectures
Azure reference architecturesAzure reference architectures
Azure reference architectures
 
10 Ways to Scale with Redis - LA Redis Meetup 2019
10 Ways to Scale with Redis - LA Redis Meetup 201910 Ways to Scale with Redis - LA Redis Meetup 2019
10 Ways to Scale with Redis - LA Redis Meetup 2019
 
Getting started with MariaDB with Docker
Getting started with MariaDB with DockerGetting started with MariaDB with Docker
Getting started with MariaDB with Docker
 
10 Ways to Scale Your Website Silicon Valley Code Camp 2019
10 Ways to Scale Your Website Silicon Valley Code Camp 201910 Ways to Scale Your Website Silicon Valley Code Camp 2019
10 Ways to Scale Your Website Silicon Valley Code Camp 2019
 
Secure Redis Cluster At Box: Vova Galchenko, Ravitej Sistla
Secure Redis Cluster At Box: Vova Galchenko, Ravitej SistlaSecure Redis Cluster At Box: Vova Galchenko, Ravitej Sistla
Secure Redis Cluster At Box: Vova Galchenko, Ravitej Sistla
 
Add Redis to Postgres to Make Your Microservices Go Boom!
Add Redis to Postgres to Make Your Microservices Go Boom!Add Redis to Postgres to Make Your Microservices Go Boom!
Add Redis to Postgres to Make Your Microservices Go Boom!
 
Scaing databases on the cloud
Scaing databases on the cloudScaing databases on the cloud
Scaing databases on the cloud
 
Scaling Databases On The Cloud
Scaling Databases On The CloudScaling Databases On The Cloud
Scaling Databases On The Cloud
 
NoSql Databases and Polyglot Applications
NoSql Databases and Polyglot ApplicationsNoSql Databases and Polyglot Applications
NoSql Databases and Polyglot Applications
 
MongoDB SF Ruby
MongoDB SF RubyMongoDB SF Ruby
MongoDB SF Ruby
 
Running database infrastructure on containers
Running database infrastructure on containersRunning database infrastructure on containers
Running database infrastructure on containers
 
Introduction to NoSQL
Introduction to NoSQLIntroduction to NoSQL
Introduction to NoSQL
 
What's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsWhat's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis Labs
 
Making (Almost) Any Database Faster and Cheaper with Caching
Making (Almost) Any Database Faster and Cheaper with CachingMaking (Almost) Any Database Faster and Cheaper with Caching
Making (Almost) Any Database Faster and Cheaper with Caching
 

More from Chris Richardson

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?Chris Richardson
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternChris Richardson
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...Chris Richardson
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Chris Richardson
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsChris Richardson
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfChris Richardson
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Chris Richardson
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...Chris Richardson
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Chris Richardson
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 Chris Richardson
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureChris Richardson
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Chris Richardson
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled servicesChris Richardson
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Chris Richardson
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...Chris Richardson
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Chris Richardson
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...Chris Richardson
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationChris Richardson
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate PlatformChris Richardson
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolithChris Richardson
 

More from Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Recently uploaded

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 

Recently uploaded (20)

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 

Developing polyglot persistence applications (devnexus 2013)

  • 1. DEVELOPING POLYGLOT PERSISTENCE APPLICATIONS Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson chris.richardson@springsource.com http://plainoldobjects.com
  • 2. Presentation goal The benefits and drawbacks of polyglot persistence and How to design applications that use this approach @crichardson
  • 3. About Chris @crichardson
  • 4. (About Chris) @crichardson
  • 5. About Chris() @crichardson
  • 6. About Chris @crichardson
  • 8. vmc push About-Chris Developer Advocate for CloudFoundry.com Signup at http://cloudfoundry.com @crichardson
  • 9. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 10. Food to Go • Take-out food delivery service • “Launched” in 2006 @crichardson
  • 11. Food To Go Architecture RESTAURANT CONSUMER OWNER Order Restaurant taking Management MySQL Database @crichardson
  • 12. Success Growth challenges • Increasing traffic • Increasing data volume • Distribute across a few data centers • Increasing domain model complexity @crichardson
  • 13. Limitations of relational databases • Scalability • Distribution • Schema updates • O/R impedance mismatch • Handling semi-structured data @crichardson
  • 14. Solution: Spend Money http://upload.wikimedia.org/wikipedia/commons/e/e5/Rising_Sun_Yacht.JPG OR http://www.trekbikes.com/us/en/bikes/road/race_performance/madone_5_series/madone_5_2/# @crichardson
  • 15. Solution: Use NoSQL Benefits Drawbacks • Higher performance • Limited transactions • Higher scalability • Limited querying • Richer data-model • Relaxed consistency • Schema-less • Unconstrained data @crichardson
  • 16. Example NoSQL Databases Database Key features Cassandra Extensible column store, very scalable, distributed Neo4j Graph database Document-oriented, fast, scalable MongoDB Redis Key-value store, very fast http://nosql-database.org/ lists 122+ NoSQL databases @crichardson
  • 17. Redis • Advanced key-value store K1 V1 • C-based server K2 V2 • Very fast, e.g. 100K reqs/sec ... ... • Optional persistence • Transactions with optimistic locking • Master-slave replication • Sharding using client-side consistent hashing @crichardson
  • 18. Sorted sets Value Key a b myset 5.0 10. Members are Score sorted by score @crichardson
  • 19. Adding members to a sorted set Redis Server Key Score Value a zadd myset 5.0 a myset 5.0 @crichardson
  • 20. Adding members to a sorted set Redis Server a b zadd myset 10.0 b myset 5.0 10. @crichardson
  • 21. Adding members to a sorted set Redis Server c a b zadd myset 1.0 c myset 1.0 5.0 10. @crichardson
  • 22. Retrieving members by index range Start End Key Index Index Redis Server zrange myset 0 1 c a b myset 1.0 5.0 10. c a @crichardson
  • 23. Retrieving members by score Min Max Key value value Redis Server zrangebyscore myset 1 6 c a b myset 1.0 5.0 10. c a @crichardson
  • 24. Redis use cases • Replacement for Memcached • Handling tasks that overload an RDBMS • Session state • Hit counts - INCR • Cache of data retrieved from • Most recent N items - LPUSH and system of record (SOR) LTRIM • Replica of SOR for queries • Randomly selecting an item – needing high-performance SRANDMEMBER • Queuing – Lists with LPOP, RPUSH, …. • High score tables – Sorted sets and ZINCRBY • … @crichardson
  • 25. Redis is great but there are tradeoffs • Low-level query language: PK-based access only • Limited transaction model: • Read first and then execute updates as batch • Difficult to compose code • Data must fit in memory • Single-threaded server: run multiple with client-side sharding • Missing features such as access control, ... @crichardson
  • 26. And don’t forget: An RDBMS is fine for many applications @crichardson
  • 27. The future is polyglot e.g. Netflix • RDBMS • SimpleDB • Cassandra • Hadoop/Hbase IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg @crichardson
  • 28. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 29. Food to Go – Domain model (partial) class Restaurant { class TimeRange { long id; long id; String name; int dayOfWeek; Set<String> serviceArea; int openTime; Set<TimeRange> openingHours; int closeTime; List<MenuItem> menuItems; } } class MenuItem { String name; double price; } @crichardson
  • 30. Database schema ID Name … RESTAURANT table 1 Ajanta 2 Montclair Eggshop Restaurant_id zipcode RESTAURANT_ZIPCODE table 1 94707 1 94619 2 94611 2 94619 RESTAURANT_TIME_RANGE table Restaurant_id dayOfWeek openTime closeTime 1 Monday 1130 1430 1 Monday 1730 2130 2 Tuesday 1130 … @crichardson
  • 31. RestaurantRepository public interface RestaurantRepository { void addRestaurant(Restaurant restaurant); Restaurant findById(long id); ... } Food To Go will have scaling eventually issues @crichardson
  • 32. Increase scalability by caching RESTAURANT CONSUMER OWNER Order Restaurant taking Management MySQL Cache Database @crichardson
  • 33. Caching Options • Where: • Hibernate 2nd level cache • Explicit calls from application code • Caching aspect • Cache technologies: Ehcache, Memcached, Infinispan, ... Redis is also an option @crichardson
  • 34. Using Redis as a cache • Spring 3.1 cache abstraction • Annotations specify which methods to cache • CacheManager - pluggable back-end cache • Spring Data for Redis • Simplifies the development of Redis applications • Provides RedisTemplate (analogous to JdbcTemplate) • Provides RedisCacheManager @crichardson
  • 35. Using Spring 3.1 Caching @Service public class RestaurantManagementServiceImpl implements RestaurantManagementService { private final RestaurantRepository restaurantRepository; @Autowired public RestaurantManagementServiceImpl(RestaurantRepository restaurantRepository) { this.restaurantRepository = restaurantRepository; } @Override public void add(Restaurant restaurant) { Cache result restaurantRepository.add(restaurant); } @Override @Cacheable(value = "Restaurant") public Restaurant findById(int id) { return restaurantRepository.findRestaurant(id); Evict from } cache @Override @CacheEvict(value = "Restaurant", key="#restaurant.id") public void update(Restaurant restaurant) { restaurantRepository.update(restaurant); } @crichardson
  • 36. Configuring the Redis Cache Manager Enables caching <cache:annotation-driven /> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" > <constructor-arg ref="restaurantTemplate"/> </bean> Specifies CacheManager The RedisTemplate used implementation to access Redis @crichardson
  • 37. Domain object to key-value mapping? Restaurant K1 V1 TimeRange TimeRange MenuItem MenuItem K2 V2 ... ... ServiceArea @crichardson
  • 38. RedisTemplate handles the mapping • Principal API provided by Spring Data to Redis • Analogous to JdbcTemplate • Encapsulates boilerplate code, e.g. connection management • Maps Java objects Redis byte[]’s @crichardson
  • 39. Serializers: object byte[] • RedisTemplate has multiple serializers • DefaultSerializer - defaults to JdkSerializationRedisSerializer • KeySerializer • ValueSerializer • HashKeySerializer • HashValueSerializer @crichardson
  • 40. Serializing a Restaurant as JSON @Configuration public class RestaurantManagementRedisConfiguration { @Autowired private RestaurantObjectMapperFactory restaurantObjectMapperFactory; private JacksonJsonRedisSerializer<Restaurant> makeRestaurantJsonSerializer() { JacksonJsonRedisSerializer<Restaurant> serializer = new JacksonJsonRedisSerializer<Restaurant>(Restaurant.class); ... return serializer; } @Bean @Qualifier("Restaurant") public RedisTemplate<String, Restaurant> restaurantTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Restaurant> template = new RedisTemplate<String, Restaurant>(); template.setConnectionFactory(factory); JacksonJsonRedisSerializer<Restaurant> jsonSerializer = makeRestaurantJsonSerializer(); template.setValueSerializer(jsonSerializer); return template; } Serialize restaurants using Jackson } JSON @crichardson
  • 41. Caching with Redis RESTAURANT CONSUMER OWNER Order Restaurant taking Management Redis MySQL First Second Cache Database @crichardson
  • 42. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 43. Finding available restaurants Available restaurants = Serve the zip code of the delivery address AND Are open at the delivery time public interface AvailableRestaurantRepository { List<AvailableRestaurant> findAvailableRestaurants(Address deliveryAddress, Date deliveryTime); ... } @crichardson
  • 44. Finding available restaurants on Monday, 6.15pm for 94619 zipcode Straightforward three-way join select r.* from restaurant r inner join restaurant_time_range tr on r.id =tr.restaurant_id inner join restaurant_zipcode sa on r.id = sa.restaurant_id where ’94619’ = sa.zip_code and tr.day_of_week=’monday’ and tr.openingtime <= 1815 and 1815 <= tr.closingtime @crichardson
  • 45. How to scale queries? @crichardson
  • 46. Option #1: Query caching • [ZipCode, DeliveryTime] ⇨ list of available restaurants BUT • Long tail queries • Update restaurant ⇨ Flush entire cache Ineffective @crichardson
  • 47. Option #2: Master/Slave replication Writes Consistent reads Queries MySQL (Inconsistent reads) Master MySQL MySQL MySQL Slave 1 Slave 2 Slave N @crichardson
  • 48. Master/Slave replication • Mostly straightforward BUT • Assumes that SQL query is efficient • Complexity of administration of slaves • Doesn’t scale writes @crichardson
  • 49. Option #3: Redis materialized views RESTAURANT CONSUMER OWNER Order Restaurant taking Management System of Copy update() Record findAvailable() MySQL Redis Cache Database @crichardson
  • 50. BUT how to implement findAvailableRestaurants() with Redis?! ? select r.* from restaurant r K1 V1 inner join restaurant_time_range tr on r.id =tr.restaurant_id inner join restaurant_zipcode sa on r.id = sa.restaurant_id K2 V2 where ’94619’ = sa.zip_code and tr.day_of_week=’monday’ and tr.openingtime <= 1815 ... ... and 1815 <= tr.closingtime @crichardson
  • 51. Solution: Build an index using sorted sets and ZRANGEBYSCORE ZRANGEBYSCORE myset 1 6 = sorted_set select value key value score from sorted_set where key = ‘myset’ and score >= 1 and score <= 6 @crichardson
  • 52. How to transform the SELECT statement? select r.* from restaurant r inner join restaurant_time_range tr on r.id =tr.restaurant_id inner join restaurant_zipcode sa ? select value from sorted_set where key = ? on r.id = sa.restaurant_id and score >= ? where ’94619’ = sa.zip_code and score <= ? and tr.day_of_week=’monday’ and tr.openingtime <= 1815 and 1815 <= tr.closingtime @crichardson
  • 53. We need to denormalize Think materialized view @crichardson
  • 54. Simplification #1: Denormalization Restaurant_id Day_of_week Open_time Close_time Zip_code 1 Monday 1130 1430 94707 1 Monday 1130 1430 94619 1 Monday 1730 2130 94707 1 Monday 1730 2130 94619 2 Monday 0700 1430 94619 … SELECT restaurant_id FROM time_range_zip_code WHERE day_of_week = ‘Monday’ Simpler query:  No joins AND zip_code = 94619  Two = and two < AND 1815 < close_time AND open_time < 1815 @crichardson
  • 55. Simplification #2: Application filtering SELECT restaurant_id, open_time FROM time_range_zip_code WHERE day_of_week = ‘Monday’ Even simpler query • No joins AND zip_code = 94619 • Two = and one < AND 1815 < close_time AND open_time < 1815 @crichardson
  • 56. Simplification #3: Eliminate multiple =’s with concatenation Restaurant_id Zip_dow Open_time Close_time 1 94707:Monday 1130 1430 1 94619:Monday 1130 1430 1 94707:Monday 1730 2130 1 94619:Monday 1730 2130 2 94619:Monday 0700 1430 … SELECT restaurant_id, open_time FROM time_range_zip_code WHERE zip_code_day_of_week = ‘94619:Monday’ AND 1815 < close_time key range @crichardson
  • 57. Simplification #4: Eliminate multiple RETURN VALUES with concatenation zip_dow open_time_restaurant_id close_time 94707:Monday 1130_1 1430 94619:Monday 1130_1 1430 94707:Monday 1730_1 2130 94619:Monday 1730_1 2130 94619:Monday 0700_2 1430 ... SELECT open_time_restaurant_id, FROM time_range_zip_code WHERE zip_code_day_of_week = ‘94619:Monday’ AND 1815 < close_time ✔ @crichardson
  • 58. Using a Redis sorted set as an index zip_dow open_time_restaurant_id close_time 94707:Monday 1130_1 1430 94619:Monday 1130_1 1430 94707:Monday 1730_1 2130 94619:Monday 1730_1 2130 94619:Monday 0700_2 1430 ... Key Sorted Set [ Entry:Score, …] 94619:Monday [0700_2:1430, 1130_1:1430, 1730_1:2130] 94707:Monday [1130_1:1430, 1730_1:2130] @crichardson
  • 59. Querying with ZRANGEBYSCORE Key Sorted Set [ Entry:Score, …] 94619:Monday [0700_2:1430, 1130_1:1430, 1730_1:2130] 94707:Monday [1130_1:1430, 1730_1:2130] Delivery zip and day Delivery time ZRANGEBYSCORE 94619:Monday 1815 2359  {1730_1} 1730 is before 1815  Ajanta is open @crichardson
  • 60. Adding a Restaurant @Component public class AvailableRestaurantRepositoryImpl implements AvailableRestaurantRepository { @Override public void add(Restaurant restaurant) { addRestaurantDetails(restaurant); Store as addAvailabilityIndexEntries(restaurant); JSON } Text private void addRestaurantDetails(Restaurant restaurant) { restaurantTemplate.opsForValue().set(keyFormatter.key(restaurant.getId()), restaurant); } private void addAvailabilityIndexEntries(Restaurant restaurant) { for (TimeRange tr : restaurant.getOpeningHours()) { String indexValue = formatTrId(restaurant, tr); key member int dayOfWeek = tr.getDayOfWeek(); int closingTime = tr.getClosingTime(); for (String zipCode : restaurant.getServiceArea()) { redisTemplate.opsForZSet().add(closingTimesKey(zipCode, dayOfWeek), indexValue, closingTime); } } } score @crichardson
  • 61. Finding available Restaurants @Component public class AvailableRestaurantRepositoryImpl implements AvailableRestaurantRepository { @Override public List<AvailableRestaurant> findAvailableRestaurants(Address deliveryAddress, Date deliveryTime) { Find those that String zipCode = deliveryAddress.getZip(); close after int dayOfWeek = DateTimeUtil.dayOfWeek(deliveryTime); int timeOfDay = DateTimeUtil.timeOfDay(deliveryTime); String closingTimesKey = closingTimesKey(zipCode, dayOfWeek); Set<String> trsClosingAfter = redisTemplate.opsForZSet().rangeByScore(closingTimesKey, timeOfDay, 2359); Set<String> restaurantIds = new HashSet<String>(); for (String tr : trsClosingAfter) { Filter out those that String[] values = tr.split("_"); open after if (Integer.parseInt(values[0]) <= timeOfDay) restaurantIds.add(values[1]); } Collection<String> keys = keyFormatter.keys(restaurantIds); return availableRestaurantTemplate.opsForValue().multiGet(keys); Retrieve open } restaurants @crichardson
  • 63. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 64. MySQL & Redis need to be consistent @crichardson
  • 65. Two-Phase commit is not an option • Redis does not support it • Even if it did, 2PC is best avoided http://www.infoq.com/articles/ebay-scalability-best-practices @crichardson
  • 66. Atomic Consistent Basically Available Isolated Soft state Durable Eventually consistent BASE: An Acid Alternative http://queue.acm.org/detail.cfm?id=1394128 @crichardson
  • 67. Updating Redis #FAIL begin MySQL transaction update MySQL Redis has update update Redis MySQL does not rollback MySQL transaction begin MySQL transaction update MySQL MySQL has update commit MySQL transaction Redis does not <<system crashes>> update Redis @crichardson
  • 68. Updating Redis reliably Step 1 of 2 begin MySQL transaction update MySQL ACID queue CRUD event in MySQL commit transaction Event Id Operation: Create, Update, Delete New entity state, e.g. JSON @crichardson
  • 69. Updating Redis reliably Step 2 of 2 for each CRUD event in MySQL queue get next CRUD event from MySQL queue If CRUD event is not duplicate then Update Redis (incl. eventId) end if begin MySQL transaction mark CRUD event as processed commit transaction @crichardson
  • 70. Step 1 Step 2 Timer EntityCrudEvent EntityCrudEvent apply(event) Redis Repository Processor Updater INSERT INTO ... SELECT ... FROM ... ENTITY_CRUD_EVENT ID JSON processed? Redis @crichardson
  • 71. Optimistic locking Updating Redis WATCH restaurant:lastSeenEventId:≪restaurantId≫ lastSeenEventId = GET restaurant:lastSeenEventId:≪restaurantId≫ Duplicate if (lastSeenEventId >= eventId) return; detection MULTI SET restaurant:lastSeenEventId:≪restaurantId≫ eventId Transaction ... update the restaurant data... EXEC @crichardson
  • 72. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 73. How do we generate CRUD events? @crichardson
  • 74. Change tracking options • Explicit code • Hibernate event listener • Service-layer aspect • CQRS/Event-sourcing @crichardson
  • 75. HibernateEvent EntityCrudEvent Listener Repository ENTITY_CRUD_EVENT ID JSON processed? @crichardson
  • 76. Hibernate event listener public class ChangeTrackingListener implements PostInsertEventListener, PostDeleteEventListener, PostUpdateEventListener { @Autowired private EntityCrudEventRepository entityCrudEventRepository; private void maybeTrackChange(Object entity, EntityCrudEventType eventType) { if (isTrackedEntity(entity)) { entityCrudEventRepository.add(new EntityCrudEvent(eventType, entity)); } } @Override public void onPostInsert(PostInsertEvent event) { Object entity = event.getEntity(); maybeTrackChange(entity, EntityCrudEventType.CREATE); } @Override public void onPostUpdate(PostUpdateEvent event) { Object entity = event.getEntity(); maybeTrackChange(entity, EntityCrudEventType.UPDATE); } @Override public void onPostDelete(PostDeleteEvent event) { Object entity = event.getEntity(); maybeTrackChange(entity, EntityCrudEventType.DELETE); } @crichardson
  • 77. Agenda • Why polyglot persistence? • Using Redis as a cache • Optimizing queries using Redis materialized views • Synchronizing MySQL and Redis • Tracking changes to entities • Using a modular asynchronous architecture @crichardson
  • 78. Original architecture WAR Restaurant Management ... @crichardson
  • 79. Drawbacks of this monolithic architecture • Obstacle to frequent WAR deployments Restaurant Management • Overloads IDE and web container ... • Obstacle to scaling development • Technology lock-in @crichardson
  • 80. Need a more modular architecture @crichardson
  • 81. Using a message broker Asynchronous is preferred JSON is fashionable but binary format is more efficient @crichardson
  • 82. Modular architecture RESTAURANT CONSUMER Timer OWNER Order Event Restaurant taking Publisher Management MySQL Redis Redis RabbitMQ Database Cache @crichardson
  • 83. Benefits of a modular asynchronous architecture • Scales development: develop, deploy and scale each service independently • Redeploy UI frequently/independently • Improves fault isolation • Eliminates long-term commitment to a single technology stack • Message broker decouples producers and consumers @crichardson
  • 84. Step 2 of 2 for each CRUD event in MySQL queue get next CRUD event from MySQL queue Publish persistent message to RabbitMQ begin MySQL transaction mark CRUD event as processed commit transaction @crichardson
  • 85. Message flow EntityCrudEvent Processor AvailableRestaurant ManagementService Redis Updater Spring Integration glue code RABBITMQ REDIS @crichardson
  • 86. RedisUpdater AMQP <beans> Creates proxy <int:gateway id="redisUpdaterGateway" service-interface="net...RedisUpdater" default-request-channel="eventChannel" /> <int:channel id="eventChannel"/> <int:object-to-json-transformer input-channel="eventChannel" output-channel="amqpOut"/> <int:channel id="amqpOut"/> <amqp:outbound-channel-adapter channel="amqpOut" amqp-template="rabbitTemplate" routing-key="crudEvents" exchange-name="crudEvents" /> </beans> @crichardson
  • 87. AMQP Available...Service <beans> <amqp:inbound-channel-adapter channel="inboundJsonEventsChannel" connection-factory="rabbitConnectionFactory" queue-names="crudEvents"/> <int:channel id="inboundJsonEventsChannel"/> <int:json-to-object-transformer input-channel="inboundJsonEventsChannel" type="net.chrisrichardson.foodToGo.common.JsonEntityCrudEvent" output-channel="inboundEventsChannel"/> <int:channel id="inboundEventsChannel"/> Invokes service <int:service-activator input-channel="inboundEventsChannel" ref="availableRestaurantManagementServiceImpl" method="processEvent"/> </beans> @crichardson
  • 88. Summary • Each SQL/NoSQL database = set of tradeoffs • Polyglot persistence: leverage the strengths of SQL and NoSQL databases • Use Redis as a distributed cache • Store denormalized data in Redis for fast querying • Reliable database synchronization required @crichardson
  • 89. @crichardson chris.richardson@springsource.com http://plainoldobjects.com - code and slides Sign up for CloudFoundry.com@crichardson