SlideShare a Scribd company logo
1 of 76
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 beneļ¬ts and drawbacks of
     polyglot persistence
             and
How to design applications that
     use this approach
About Chris
(About Chris)
About Chris()
About Chris
About Chris




http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/
vmc push About-Chris


    Developer Advocate for
      CloudFoundry.com


Signup at http://cloudfoundry.com
Agenda

ā€¢ Why     polyglot persistence?

ā€¢ Using   Redis as a cache

ā€¢ Optimizing    queries using Redis materialized views

ā€¢ Synchronizing   MySQL and Redis

ā€¢ Tracking   changes to entities
Food to Go



ā€¢ Take-out   food delivery
 service

ā€¢ ā€œLaunchedā€ in   2006
Food To Go Architecture
                              RESTAURANT
        CONSUMER
                                OWNER


   Order                Restaurant
   taking              Management



            MySQL
            Database
Success                  Growth challenges


ā€¢ Increasing   trafļ¬c

ā€¢ Increasing   data volume

ā€¢ Distribute   across a few data centers

ā€¢ Increasing   domain model complexity
Limitations of relational
                    databases

ā€¢ Scalability

ā€¢ Distribution

ā€¢ Schema   updates

ā€¢ O/R   impedance mismatch

ā€¢ Handling   semi-structured data
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/#
Solution: Use NoSQL
    Beneļ¬ts                  Drawbacks

ā€¢   Higher performance   ā€¢   Limited transactions

ā€¢   Higher scalability   ā€¢   Limited querying

ā€¢   Richer data-model    ā€¢   Relaxed consistency

ā€¢   Schema-less          ā€¢   Unconstrained data
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
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
Sorted sets
                                 Value
       Key

                            a       b
                   myset
                           5.0     10.




 Members are               Score
sorted by score
Adding members to a sorted set
                            Redis Server

   Key    Score     Value

                                            a
 zadd myset 5.0 a             myset
                                           5.0
Adding members to a sorted set
                     Redis Server




                                     a     b
 zadd myset 10.0 b     myset
                                    5.0   10.
Adding members to a sorted set
                    Redis Server




                               c     a     b
 zadd myset 1.0 c     myset
                              1.0   5.0   10.
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
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
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
                                           ā€¢   ā€¦
Redis is great but there are
                     tradeoffs
ā€¢   Low-level query language: PK-based access only

ā€¢   Limited transaction model:

    ā€¢   Read ļ¬rst and then execute updates as batch

    ā€¢   Difļ¬cult to compose code

ā€¢   Data must ļ¬t in memory

ā€¢   Single-threaded server: run multiple with client-side sharding

ā€¢   Missing features such as access control, ...
And donā€™t forget:

An RDBMS is ļ¬ne for many
      applications
The future is polyglot


                                                                        e.g. Netļ¬‚ix
                                                                        ā€¢ RDBMS
                                                                        ā€¢ SimpleDB
                                                                        ā€¢ Cassandra
                                                                        ā€¢ Hadoop/Hbase




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

ā€¢ Why     polyglot persistence?

ā€¢ Using   Redis as a cache

ā€¢ Optimizing    queries using Redis materialized views

ā€¢ Synchronizing   MySQL and Redis

ā€¢ Tracking   changes to entities
Increase scalability by caching
                            RESTAURANT
          CONSUMER
                              OWNER


     Order            Restaurant
     taking          Management



                 MySQL
         Cache
                 Database
Caching Options
ā€¢   Where:

    ā€¢   Hibernate 2nd level cache

    ā€¢   Explicit calls from application code

    ā€¢   Caching aspect

ā€¢   Cache technologies: Ehcache, Memcached, Inļ¬nispan, ...



                Redis is also an option
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

    ā€¢   Simpliļ¬es the development of Redis applications

    ā€¢   Provides RedisTemplate (analogous to JdbcTemplate)

    ā€¢   Provides RedisCacheManager
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);
  }
Conļ¬guring the Redis Cache
              Manager
         Enables caching


	   <cache:annotation-driven />

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




    Speciļ¬es CacheManager                  The RedisTemplate used
        implementation                         to access Redis
Domain object to key-value
          mapping?

      Restaurant
                         K1    V1


TimeRange
TimeRange     MenuItem
              MenuItem   K2    V2

                         ...   ...
     ServiceArea
RedisTemplate


ā€¢ Analogous   to JdbcTemplate

ā€¢ Encapsulates   boilerplate code, e.g. connection management

ā€¢ Maps   Java objects         Redis byte[]ā€™s
Serializers: object                       byte[]

ā€¢ RedisTemplate     has multiple serializers

ā€¢ DefaultSerializer   - defaults to JdkSerializationRedisSerializer

ā€¢ KeySerializer

ā€¢ ValueSerializer

ā€¢ HashKeySerializer

ā€¢ HashValueSerializer
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
Caching with Redis
                               RESTAURANT
             CONSUMER
                                 OWNER


        Order            Restaurant
        taking          Management



            Redis   MySQL
First                                 Second
            Cache   Database
Agenda

ā€¢ Why     polyglot persistence?

ā€¢ Using   Redis as a cache

ā€¢ Optimizing    queries using Redis materialized views

ā€¢ Synchronizing   MySQL and Redis

ā€¢ Tracking   changes to entities
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>
	

 ļ¬ndAvailableRestaurants(Address deliveryAddress, Date deliveryTime);
   ...
}
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;
                  }
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             ā€¦
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
How to scale queries?
Option #1: Query caching


ā€¢ [ZipCode, DeliveryTime]   ā‡Ø list of available restaurants

                              BUT

ā€¢ Long   tail queries

ā€¢ Update   restaurant ā‡Ø Flush entire cache

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



                                               Queries
                           MySQL
                                         (Inconsistent reads)
                           Master




        MySQL              MySQL               MySQL
        Slave 1            Slave 2             Slave N
Master/Slave replication

ā€¢ Mostly   straightforward

                                BUT

ā€¢ Assumes    that SQL query is efļ¬cient

ā€¢ Complexity    of administration of slaves

ā€¢ Doesnā€™t   scale writes
Option #3: Redis materialized
             views
                                          RESTAURANT
                  CONSUMER
                                            OWNER


            Order                   Restaurant
            taking                 Management       System
                                                    of
Copy                    update()                    Record
       ļ¬ndAvailable()
                                         MySQL
          Redis              Cache
                                         Database
BUT how to implement ļ¬ndAvailableRestaurants()
                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




 Solution: Build an index using sorted
       sets and ZRANGEBYSCORE
Where we need to be
ZRANGEBYSCORE myset 1 6

           =
                          sorted_set
select value,score         key value score
from sorted_set
where key = ā€˜mysetā€™
  and score >= 1
  and score <= 6
We need to denormalize


Think materialized view
Simpliļ¬cation #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
Simpliļ¬cation #2: Application
             ļ¬ltering
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
Simpliļ¬cation #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
Simpliļ¬cation #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
                                                          āœ”
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]
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
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
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
Sorry Ted!




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

ā€¢ Why     polyglot persistence?

ā€¢ Using   Redis as a cache

ā€¢ Optimizing    queries using Redis materialized views

ā€¢ Synchronizing   MySQL and Redis

ā€¢ Tracking   changes to entities
MySQL & Redis
need to be consistent
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
Atomic
Consistent                               Basically Available
Isolated                                 Soft state
Durable                                  Eventually consistent




BASE: An Acid Alternative http://queue.acm.org/detail.cfm?id=1394128
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
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
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
Step 1               Step 2
                                      Timer
  EntityCrudEvent          EntityCrudEvent   apply(event)    Redis
    Repository                Processor                     Updater



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


      ENTITY_CRUD_EVENT


            ID            JSON     processed?
                                                            Redis
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
Agenda

ā€¢ Why     polyglot persistence?

ā€¢ Using   Redis as a cache

ā€¢ Optimizing    queries using Redis materialized views

ā€¢ Synchronizing   MySQL and Redis

ā€¢ Tracking   changes to entities
How do we generate CRUD
        events?
Change tracking options


ā€¢ Explicit   code

ā€¢ Hibernate    event listener

ā€¢ Service-layer     aspect

ā€¢ CQRS/Event-sourcing
HibernateEvent              EntityCrudEvent
   Listener                   Repository




      ENTITY_CRUD_EVENT


            ID            JSON    processed?
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);
 }
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 chris.richardson@springsource.com
          http://plainoldobjects.com




             Questions?
 Sign up for CloudFoundry.com

More Related Content

What's hot

Less08 managing data and concurrency
Less08 managing data and concurrencyLess08 managing data and concurrency
Less08 managing data and concurrency
Imran Ali
Ā 
Get Your Insecure PostgreSQL Passwords to SCRAM
Get Your Insecure PostgreSQL Passwords to SCRAMGet Your Insecure PostgreSQL Passwords to SCRAM
Get Your Insecure PostgreSQL Passwords to SCRAM
Jonathan Katz
Ā 
AWS (Amazon Redshift) presentation
AWS (Amazon Redshift) presentationAWS (Amazon Redshift) presentation
AWS (Amazon Redshift) presentation
Volodymyr Rovetskiy
Ā 
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
DataStax
Ā 

What's hot (20)

Less08 managing data and concurrency
Less08 managing data and concurrencyLess08 managing data and concurrency
Less08 managing data and concurrency
Ā 
Oracle Exadata Maintenance tasks 101 - OTN Tour 2015
Oracle Exadata Maintenance tasks 101 - OTN Tour 2015Oracle Exadata Maintenance tasks 101 - OTN Tour 2015
Oracle Exadata Maintenance tasks 101 - OTN Tour 2015
Ā 
Oracle Database in-Memory Overivew
Oracle Database in-Memory OverivewOracle Database in-Memory Overivew
Oracle Database in-Memory Overivew
Ā 
InfluxDB IOx Tech Talks: Query Processing in InfluxDB IOx
InfluxDB IOx Tech Talks: Query Processing in InfluxDB IOxInfluxDB IOx Tech Talks: Query Processing in InfluxDB IOx
InfluxDB IOx Tech Talks: Query Processing in InfluxDB IOx
Ā 
[EPPG] Oracle to PostgreSQL, Challenges to Opportunity
[EPPG] Oracle to PostgreSQL, Challenges to Opportunity[EPPG] Oracle to PostgreSQL, Challenges to Opportunity
[EPPG] Oracle to PostgreSQL, Challenges to Opportunity
Ā 
Get Your Insecure PostgreSQL Passwords to SCRAM
Get Your Insecure PostgreSQL Passwords to SCRAMGet Your Insecure PostgreSQL Passwords to SCRAM
Get Your Insecure PostgreSQL Passwords to SCRAM
Ā 
Building a modern data warehouse
Building a modern data warehouseBuilding a modern data warehouse
Building a modern data warehouse
Ā 
AWS (Amazon Redshift) presentation
AWS (Amazon Redshift) presentationAWS (Amazon Redshift) presentation
AWS (Amazon Redshift) presentation
Ā 
Data platform architecture principles - ieee infrastructure 2020
Data platform architecture principles - ieee infrastructure 2020Data platform architecture principles - ieee infrastructure 2020
Data platform architecture principles - ieee infrastructure 2020
Ā 
Introduction to Amazon DynamoDB
Introduction to Amazon DynamoDBIntroduction to Amazon DynamoDB
Introduction to Amazon DynamoDB
Ā 
Oracle Weblogic for EBS and obiee (R12.2)
Oracle Weblogic for EBS and obiee (R12.2)Oracle Weblogic for EBS and obiee (R12.2)
Oracle Weblogic for EBS and obiee (R12.2)
Ā 
Improving Apache Spark's Reliability with DataSourceV2
Improving Apache Spark's Reliability with DataSourceV2Improving Apache Spark's Reliability with DataSourceV2
Improving Apache Spark's Reliability with DataSourceV2
Ā 
InfluxDB 101 - Concepts and Architecture | Michael DeSa | InfluxData
InfluxDB 101 - Concepts and Architecture | Michael DeSa | InfluxDataInfluxDB 101 - Concepts and Architecture | Michael DeSa | InfluxData
InfluxDB 101 - Concepts and Architecture | Michael DeSa | InfluxData
Ā 
Achieving Lakehouse Models with Spark 3.0
Achieving Lakehouse Models with Spark 3.0Achieving Lakehouse Models with Spark 3.0
Achieving Lakehouse Models with Spark 3.0
Ā 
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Using AWS for Backup and Restore (backup in the cloud, backup to the cloud, a...
Ā 
Creating a Modern Data Architecture
Creating a Modern Data ArchitectureCreating a Modern Data Architecture
Creating a Modern Data Architecture
Ā 
Apache Iceberg Presentation for the St. Louis Big Data IDEA
Apache Iceberg Presentation for the St. Louis Big Data IDEAApache Iceberg Presentation for the St. Louis Big Data IDEA
Apache Iceberg Presentation for the St. Louis Big Data IDEA
Ā 
Oracle Enterprise Manager
Oracle Enterprise ManagerOracle Enterprise Manager
Oracle Enterprise Manager
Ā 
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
Cassandra Backups and Restorations Using Ansible (Joshua Wickman, Knewton) | ...
Ā 
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
Ā 

Viewers also liked

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
Ā 
Developing polyglot persistence applications (SpringOne China 2012)
Developing polyglot persistence applications (SpringOne China 2012)Developing polyglot persistence applications (SpringOne China 2012)
Developing polyglot persistence applications (SpringOne China 2012)
Chris Richardson
Ā 

Viewers also liked (20)

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 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)
Ā 
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
Ā 
Developing polyglot persistence applications (devnexus 2013)
Developing polyglot persistence applications (devnexus 2013)Developing polyglot persistence applications (devnexus 2013)
Developing polyglot persistence applications (devnexus 2013)
Ā 
Developing applications with Cloud Services (Devnexus 2013)
Developing applications with Cloud Services (Devnexus 2013)Developing applications with Cloud Services (Devnexus 2013)
Developing applications with Cloud Services (Devnexus 2013)
Ā 
Developing applications with Cloud Services #javaone 2012
Developing applications with Cloud Services  #javaone 2012Developing applications with Cloud Services  #javaone 2012
Developing applications with Cloud Services #javaone 2012
Ā 
Developing polyglot applications on Cloud Foundry (#oredev 2012)
Developing polyglot applications on Cloud Foundry (#oredev 2012)Developing polyglot applications on Cloud Foundry (#oredev 2012)
Developing polyglot applications on Cloud Foundry (#oredev 2012)
Ā 
Developing polyglot persistence applications #javaone 2012
Developing polyglot persistence applications  #javaone 2012Developing polyglot persistence applications  #javaone 2012
Developing polyglot persistence applications #javaone 2012
Ā 
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...
Ā 
Using Spring with NoSQL databases (SpringOne China 2012)
Using Spring with NoSQL databases (SpringOne China 2012)Using Spring with NoSQL databases (SpringOne China 2012)
Using Spring with NoSQL databases (SpringOne China 2012)
Ā 
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)
Ā 
Developing polyglot persistence applications (SpringOne China 2012)
Developing polyglot persistence applications (SpringOne China 2012)Developing polyglot persistence applications (SpringOne China 2012)
Developing polyglot persistence applications (SpringOne China 2012)
Ā 
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)
Ā 
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...
Ā 
AppliFire Blue Print Design Guidelines
AppliFire Blue Print Design GuidelinesAppliFire Blue Print Design Guidelines
AppliFire Blue Print Design Guidelines
Ā 
Introduction to Redis Data Structures: Sorted Sets
Introduction to Redis Data Structures: Sorted SetsIntroduction to Redis Data Structures: Sorted Sets
Introduction to Redis Data Structures: Sorted Sets
Ā 
Introduction to some top Redis use cases
Introduction to some top Redis use casesIntroduction to some top Redis use cases
Introduction to some top Redis use cases
Ā 

Similar to Developing polyglot persistence applications (SpringOne India 2012)

RedisConf18 - Designing a Redis Client for Humans
RedisConf18 - Designing a Redis Client for Humans RedisConf18 - Designing a Redis Client for Humans
RedisConf18 - Designing a Redis Client for Humans
Redis Labs
Ā 
RedisConf18 - Redis Enterprise on Cloud Native Platforms
RedisConf18 - Redis Enterprise on Cloud  Native  Platforms RedisConf18 - Redis Enterprise on Cloud  Native  Platforms
RedisConf18 - Redis Enterprise on Cloud Native Platforms
Redis Labs
Ā 
Karwin bill zf-db-zend_con-20071009
Karwin bill zf-db-zend_con-20071009Karwin bill zf-db-zend_con-20071009
Karwin bill zf-db-zend_con-20071009
robinvnxxx
Ā 

Similar to Developing polyglot persistence applications (SpringOne India 2012) (20)

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
Ā 
Running database infrastructure on containers
Running database infrastructure on containersRunning database infrastructure on containers
Running database infrastructure on containers
Ā 
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?
Ā 
KeyValue Stores
KeyValue StoresKeyValue Stores
KeyValue Stores
Ā 
Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)Developing polyglot persistence applications (svcc, svcc2013)
Developing polyglot persistence applications (svcc, svcc2013)
Ā 
MySQL Load Balancers - MaxScale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
MySQL Load Balancers - MaxScale, ProxySQL, HAProxy, MySQL Router & nginx - A ...MySQL Load Balancers - MaxScale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
MySQL Load Balancers - MaxScale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
Ā 
RedisConf18 - Designing a Redis Client for Humans
RedisConf18 - Designing a Redis Client for Humans RedisConf18 - Designing a Redis Client for Humans
RedisConf18 - Designing a Redis Client for Humans
Ā 
Getting started with MariaDB with Docker
Getting started with MariaDB with DockerGetting started with MariaDB with Docker
Getting started with MariaDB with Docker
Ā 
DAT201 Migrating Databases to AWS - AWS re: Invent 2012
DAT201 Migrating Databases to AWS - AWS re: Invent 2012DAT201 Migrating Databases to AWS - AWS re: Invent 2012
DAT201 Migrating Databases to AWS - AWS re: Invent 2012
Ā 
Deep Dive on MySQL Databases on AWS - AWS Online Tech Talks
Deep Dive on MySQL Databases on AWS - AWS Online Tech TalksDeep Dive on MySQL Databases on AWS - AWS Online Tech Talks
Deep Dive on MySQL Databases on AWS - AWS Online Tech Talks
Ā 
Redis by-hari
Redis by-hariRedis by-hari
Redis by-hari
Ā 
How does Apache Pegasus (incubating) community develop at SensorsData
How does Apache Pegasus (incubating) community develop at SensorsDataHow does Apache Pegasus (incubating) community develop at SensorsData
How does Apache Pegasus (incubating) community develop at SensorsData
Ā 
MariaDB 10.1 what's new and what's coming in 10.2 - Tokyo MariaDB Meetup
MariaDB 10.1   what's new and what's coming in 10.2 - Tokyo MariaDB MeetupMariaDB 10.1   what's new and what's coming in 10.2 - Tokyo MariaDB Meetup
MariaDB 10.1 what's new and what's coming in 10.2 - Tokyo MariaDB Meetup
Ā 
(DAT407) Amazon ElastiCache: Deep Dive
(DAT407) Amazon ElastiCache: Deep Dive(DAT407) Amazon ElastiCache: Deep Dive
(DAT407) Amazon ElastiCache: Deep Dive
Ā 
Databases in the hosted cloud
Databases in the hosted cloudDatabases in the hosted cloud
Databases in the hosted cloud
Ā 
RedisConf18 - Redis Enterprise on Cloud Native Platforms
RedisConf18 - Redis Enterprise on Cloud  Native  Platforms RedisConf18 - Redis Enterprise on Cloud  Native  Platforms
RedisConf18 - Redis Enterprise on Cloud Native Platforms
Ā 
Karwin bill zf-db-zend_con-20071009
Karwin bill zf-db-zend_con-20071009Karwin bill zf-db-zend_con-20071009
Karwin bill zf-db-zend_con-20071009
Ā 
MongoDB SF Ruby
MongoDB SF RubyMongoDB SF Ruby
MongoDB SF Ruby
Ā 
MariaDB 10: A MySQL Replacement - HKOSC
MariaDB 10: A MySQL Replacement - HKOSC MariaDB 10: A MySQL Replacement - HKOSC
MariaDB 10: A MySQL Replacement - HKOSC
Ā 
MySQL Load Balancers - Maxscale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
MySQL Load Balancers - Maxscale, ProxySQL, HAProxy, MySQL Router & nginx - A ...MySQL Load Balancers - Maxscale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
MySQL Load Balancers - Maxscale, ProxySQL, HAProxy, MySQL Router & nginx - A ...
Ā 

More from Chris 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

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(ā˜Žļø+971_581248768%)**%*]'#abortion pills for sale in dubai@
Ā 

Recently uploaded (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Ā 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
Ā 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
Ā 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
Ā 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Ā 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
Ā 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Ā 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
Ā 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
Ā 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Ā 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
Ā 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
Ā 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
Ā 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
Ā 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜
Ā 
Scaling API-first ā€“ The story of a global engineering organization
Scaling API-first ā€“ The story of a global engineering organizationScaling API-first ā€“ The story of a global engineering organization
Scaling API-first ā€“ The story of a global engineering organization
Ā 

Developing polyglot persistence applications (SpringOne India 2012)

  • 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 beneļ¬ts and drawbacks of polyglot persistence and How to design applications that use this approach
  • 8. vmc push About-Chris Developer Advocate for CloudFoundry.com Signup at http://cloudfoundry.com
  • 9. Agenda ā€¢ Why polyglot persistence? ā€¢ Using Redis as a cache ā€¢ Optimizing queries using Redis materialized views ā€¢ Synchronizing MySQL and Redis ā€¢ Tracking changes to entities
  • 10. Food to Go ā€¢ Take-out food delivery service ā€¢ ā€œLaunchedā€ in 2006
  • 11. Food To Go Architecture RESTAURANT CONSUMER OWNER Order Restaurant taking Management MySQL Database
  • 12. Success Growth challenges ā€¢ Increasing trafļ¬c ā€¢ Increasing data volume ā€¢ Distribute across a few data centers ā€¢ Increasing domain model complexity
  • 13. Limitations of relational databases ā€¢ Scalability ā€¢ Distribution ā€¢ Schema updates ā€¢ O/R impedance mismatch ā€¢ Handling semi-structured data
  • 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/#
  • 15. Solution: Use NoSQL Beneļ¬ts Drawbacks ā€¢ Higher performance ā€¢ Limited transactions ā€¢ Higher scalability ā€¢ Limited querying ā€¢ Richer data-model ā€¢ Relaxed consistency ā€¢ Schema-less ā€¢ Unconstrained data
  • 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
  • 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
  • 18. Sorted sets Value Key a b myset 5.0 10. Members are Score sorted by score
  • 19. Adding members to a sorted set Redis Server Key Score Value a zadd myset 5.0 a myset 5.0
  • 20. Adding members to a sorted set Redis Server a b zadd myset 10.0 b myset 5.0 10.
  • 21. Adding members to a sorted set Redis Server c a b zadd myset 1.0 c myset 1.0 5.0 10.
  • 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
  • 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
  • 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 ā€¢ ā€¦
  • 25. Redis is great but there are tradeoffs ā€¢ Low-level query language: PK-based access only ā€¢ Limited transaction model: ā€¢ Read ļ¬rst and then execute updates as batch ā€¢ Difļ¬cult to compose code ā€¢ Data must ļ¬t in memory ā€¢ Single-threaded server: run multiple with client-side sharding ā€¢ Missing features such as access control, ...
  • 26. And donā€™t forget: An RDBMS is ļ¬ne for many applications
  • 27. The future is polyglot e.g. Netļ¬‚ix ā€¢ RDBMS ā€¢ SimpleDB ā€¢ Cassandra ā€¢ Hadoop/Hbase IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg
  • 28. Agenda ā€¢ Why polyglot persistence? ā€¢ Using Redis as a cache ā€¢ Optimizing queries using Redis materialized views ā€¢ Synchronizing MySQL and Redis ā€¢ Tracking changes to entities
  • 29. Increase scalability by caching RESTAURANT CONSUMER OWNER Order Restaurant taking Management MySQL Cache Database
  • 30. Caching Options ā€¢ Where: ā€¢ Hibernate 2nd level cache ā€¢ Explicit calls from application code ā€¢ Caching aspect ā€¢ Cache technologies: Ehcache, Memcached, Inļ¬nispan, ... Redis is also an option
  • 31. 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 ā€¢ Simpliļ¬es the development of Redis applications ā€¢ Provides RedisTemplate (analogous to JdbcTemplate) ā€¢ Provides RedisCacheManager
  • 32. 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); }
  • 33. Conļ¬guring the Redis Cache Manager Enables caching <cache:annotation-driven /> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" > <constructor-arg ref="restaurantTemplate"/> </bean> Speciļ¬es CacheManager The RedisTemplate used implementation to access Redis
  • 34. Domain object to key-value mapping? Restaurant K1 V1 TimeRange TimeRange MenuItem MenuItem K2 V2 ... ... ServiceArea
  • 35. RedisTemplate ā€¢ Analogous to JdbcTemplate ā€¢ Encapsulates boilerplate code, e.g. connection management ā€¢ Maps Java objects Redis byte[]ā€™s
  • 36. Serializers: object byte[] ā€¢ RedisTemplate has multiple serializers ā€¢ DefaultSerializer - defaults to JdkSerializationRedisSerializer ā€¢ KeySerializer ā€¢ ValueSerializer ā€¢ HashKeySerializer ā€¢ HashValueSerializer
  • 37. 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
  • 38. Caching with Redis RESTAURANT CONSUMER OWNER Order Restaurant taking Management Redis MySQL First Second Cache Database
  • 39. Agenda ā€¢ Why polyglot persistence? ā€¢ Using Redis as a cache ā€¢ Optimizing queries using Redis materialized views ā€¢ Synchronizing MySQL and Redis ā€¢ Tracking changes to entities
  • 40. 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> ļ¬ndAvailableRestaurants(Address deliveryAddress, Date deliveryTime); ... }
  • 41. 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; }
  • 42. 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 ā€¦
  • 43. 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
  • 44. How to scale queries?
  • 45. Option #1: Query caching ā€¢ [ZipCode, DeliveryTime] ā‡Ø list of available restaurants BUT ā€¢ Long tail queries ā€¢ Update restaurant ā‡Ø Flush entire cache Ineffective
  • 46. Option #2: Master/Slave replication Writes Consistent reads Queries MySQL (Inconsistent reads) Master MySQL MySQL MySQL Slave 1 Slave 2 Slave N
  • 47. Master/Slave replication ā€¢ Mostly straightforward BUT ā€¢ Assumes that SQL query is efļ¬cient ā€¢ Complexity of administration of slaves ā€¢ Doesnā€™t scale writes
  • 48. Option #3: Redis materialized views RESTAURANT CONSUMER OWNER Order Restaurant taking Management System of Copy update() Record ļ¬ndAvailable() MySQL Redis Cache Database
  • 49. BUT how to implement ļ¬ndAvailableRestaurants() 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 Solution: Build an index using sorted sets and ZRANGEBYSCORE
  • 50. Where we need to be ZRANGEBYSCORE myset 1 6 = sorted_set select value,score key value score from sorted_set where key = ā€˜mysetā€™ and score >= 1 and score <= 6
  • 51. We need to denormalize Think materialized view
  • 52. Simpliļ¬cation #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
  • 53. Simpliļ¬cation #2: Application ļ¬ltering 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
  • 54. Simpliļ¬cation #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
  • 55. Simpliļ¬cation #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 āœ”
  • 56. 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]
  • 57. 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
  • 58. 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
  • 59. 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
  • 61. Agenda ā€¢ Why polyglot persistence? ā€¢ Using Redis as a cache ā€¢ Optimizing queries using Redis materialized views ā€¢ Synchronizing MySQL and Redis ā€¢ Tracking changes to entities
  • 62. MySQL & Redis need to be consistent
  • 63. 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
  • 64. Atomic Consistent Basically Available Isolated Soft state Durable Eventually consistent BASE: An Acid Alternative http://queue.acm.org/detail.cfm?id=1394128
  • 65. 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
  • 66. 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
  • 67. 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
  • 68. Step 1 Step 2 Timer EntityCrudEvent EntityCrudEvent apply(event) Redis Repository Processor Updater INSERT INTO ... SELECT ... FROM ... ENTITY_CRUD_EVENT ID JSON processed? Redis
  • 69. 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
  • 70. Agenda ā€¢ Why polyglot persistence? ā€¢ Using Redis as a cache ā€¢ Optimizing queries using Redis materialized views ā€¢ Synchronizing MySQL and Redis ā€¢ Tracking changes to entities
  • 71. How do we generate CRUD events?
  • 72. Change tracking options ā€¢ Explicit code ā€¢ Hibernate event listener ā€¢ Service-layer aspect ā€¢ CQRS/Event-sourcing
  • 73. HibernateEvent EntityCrudEvent Listener Repository ENTITY_CRUD_EVENT ID JSON processed?
  • 74. 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); }
  • 75. 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
  • 76. @crichardson chris.richardson@springsource.com http://plainoldobjects.com Questions? Sign up for CloudFoundry.com