Weitere Ă€hnliche Inhalte Ăhnlich wie Open Sourcing GemFire - Apache Geode (20) KĂŒrzlich hochgeladen (20) Open Sourcing GemFire - Apache Geode2. 2© Copyright 2015 Pivotal. All rights reserved. 2© Copyright 2015 Pivotal. All rights reserved.
Open Sourcing
GemFire
An Introduction to Apache Geode (incubating)
The open source distributed in-memory database
Anthony Baker
abaker@apache.org
@metatype
Dan Smith
dsmith@pivotal.io
3. 3© Copyright 2015 Pivotal. All rights reserved.
Topics
ï GemFire history, architecture, and use cases
ï Geode, the open source core of GemFire
ï Example application and demo
ï Technical deep dive
4. 4© Copyright 2015 Pivotal. All rights reserved.
Itâs all about the
DATAand how you use it
5. 5© Copyright 2015 Pivotal. All rights reserved.
2004 2008 2014
âą Massive increase in data
volumes
âą Falling margins per
transaction
âą Increasing cost of IT
maintenance
âą Need for elasticity in
systems
âą Financial Services
Providers (every major
Wall Street bank)
âą Department of Defense
âą Real Time response needs
âą Time to market constraints
âą Need for flexible data
models across enterprise
âą Distributed development
âą Persistence + In-memory
âą Global data visibility needs
âą Fast Ingest needs for data
âą Need to allow devices to
hook into enterprise data
âą Always on
âą Largest travel Portal
âą Airlines
âą Trade clearing
âą Online gambling
âą Largest Telcos
âą Large mfrers
âą Largest Payroll processor
âą Auto insurance giants
âą Largest rail systems on
earth
Hybrid Transactional
/Analytics grids
Our GemFire Journey Over The Years
6. 6© Copyright 2015 Pivotal. All rights reserved.
Apps at Scale Have Unique Needs
Pivotal GemFire is the distributed, in-memory database for
apps that need:
1. Elastic scale-out performance
2. High performance database capabilities in distributed systems
3. Mission critical availability and resiliency
4. Flexibility for developers to create unique applications
5. Easy administration of distributed data grids
7. 7© Copyright 2015 Pivotal. All rights reserved.
1. Elastic Scale-Out Performance
Nodes
Ops /
SecLinear scalability
Elastic capacity +/-
Latency-minimizing
data distribution
China Railway
Corporation
âThe system is operating with solid
performance and uptime. Now, we have a
reliable, economically sound production
system that supports record volumes and
has room to growâ
Dr. Jiansheng Zhu, Vice Director of China
Academy of Railway Sciences
âą 4.5 million ticket purchases & 20
million users per day.
âą Spikes of 15,000 tickets sold per
minute, 40,000 visits per second.
8. 8© Copyright 2015 Pivotal. All rights reserved.
2. High Performance Database Capabilities
Performance-
optimized
persistence
Configurable
consistency Partitioned Replicated Disabled
Distributed &
continuous queries
Distributed transactions, indexing, archival
Newedge
âOur global deployment of Pivotal
GemFireâs distributed cache gives me a
single version of the trade â resolving
hard-to-test-for synchronization issues
that exist within any globally distributed
business application architectureâ
Michael Benillouche, Global Head of Data
Management
9. 9© Copyright 2015 Pivotal. All rights reserved.
3. Mission Critical Availability and Resiliency
Cluster to cluster
WAN connectivity
Cluster resilience
& failover
XX Gire
âWe can track and collect money at our
4,000+ kiosks and branches â even without
a reliable Internet connection. GemFire
provides the core data grid and a significant
amount of related functionality to help us
handle this unreliable network problemâ
Gustavo Valdez, Chief of Architecture and
Development
âą 19 million payment transactions per
month
âą 4000+ points of sale with intermittent
Internet connectivity
10. 10© Copyright 2015 Pivotal. All rights reserved.
4. Flexibility for Developers to Create Unique
Apps
âą Data Structures:
â User-defined classes
â Documents (JSON)
âą Native language support:
â Java, C++, C#
âą APIâs
â Java: Hashmap
â Memcache
â Spring Data GemFire
â C++ Serialization APIâs
âą Embedded query authoring
â Object Query Language (OQL)
âą Publish & subscribe framework for
continous query & reliable
asynchronous event queues
âą App-server embedded functionality:
â Web app session state caching
â L2 Hibernate
11. 11© Copyright 2015 Pivotal. All rights reserved.
5. Easy Administration of Distributed Data
Grids
âą Auto tuning of distributed computing resources to optimize
performance
âą Cluster monitoring dashboard
â Cluster and node status & performance
âą Offline performance statistics analysis tool
â View historical logs and events to diagnose performance and resource bottlenecks
âą Command-line tool for taking action on clusters and nodes
12. 12© Copyright 2015 Pivotal. All rights reserved.
What makes it fast?
ï Design center is RAM not HDD
ï Really demanding customers
ï Avoid and minimize, particularly on the critical read/write paths:
â Network hops, copying data, contention, distributed locking, disk seeks, garbage
ï Lots and lots of testing
â Establish and monitor performance baselines
â Distributed systems testing is difficult!
13. 13© Copyright 2015 Pivotal. All rights reserved.
Horizontal Scaling for GemFire (Geode) Reads
With Consistent Latency and CPU
âą Scaled from 256 clients and 2 servers to 1280 clients and 10 servers
âą Partitioned region with redundancy and 1K data size
0
2
4
6
8
10
12
14
16
18
0
1
2
3
4
5
6
2 4 6 8 10
Speedup
Server Hosts
speedup
latency (ms)
CPU %
14. 14© Copyright 2015 Pivotal. All rights reserved.
GemFire (Geode) 3.5-4.5X Faster Than Cassandra
for YCSB
15. 15© Copyright 2015 Pivotal. All rights reserved.
Roadmap
ï HDFS persistence
ï Off-heap storage
ï Lucene indexes
ï Spark integration
ï Cloud Foundry service
âŠand other ideas from the Geode community!
16. 16© Copyright 2015 Pivotal. All rights reserved. 16© Copyright 2015 Pivotal. All rights reserved.
Use cases and patterns
17. 17© Copyright 2015 Pivotal. All rights reserved.
âLow touchâ Usage Patterns
Simple template for TCServer, TC, App servers
Shared nothing persistence, Global session state
HTTP Session management
Set Cache in hibernate.cfg.xml
Support for query and entity caching
Hibernate L2 Cache plugin
Servers understand the memcached wire protocol
Use any memcached client
Memcached protocol
<bean id="cacheManager"
class="org.springframework.data.gemfire.support.GemfireCacheManager"Spring Cache Abstraction
18. 18© Copyright 2015 Pivotal. All rights reserved.
Application Patterns
ï Caching for speed and scale
â Read-through, Write-through, Write-behind
ï Geode as the OLTP system of record
â Data in-memory for low latency, on disk for durability
ï Parallel compute engine
ï Real-time analytics
19. 19© Copyright 2015 Pivotal. All rights reserved.
Development Patterns
ï Configure the cluster programmatically or declaratively
using cache.xml, gfsh, or SpringDataGemFire
<cache>
<region name="turbineSensorData" refid="PARTITION_PERSISTENT">
<partition-attributes redundant-copies="1" total-num-buckets="43"/>
</region>
</cache>
20. 20© Copyright 2015 Pivotal. All rights reserved.
Development Patterns
ï Write key-value data into a Region using { create | put |
putAll | remove }
â The value can be flat data, nested objects, JSON, âŠ
Region sensorData = cache.getRegion("TurbineSensorData");
SensorKey key = new SensorKey(31415926, "2013-05-19T19:22Z"); // turbineId, timestamp
sensorData.put(key, new TurbineReading()
.setAmbientTemp(75)
.setOperatingTemp(80)
.setWindDirection(0)
.setWindSpeed(30)
.setPowerOutput(5000)
.setRPM(5));
21. 21© Copyright 2015 Pivotal. All rights reserved.
Development Patterns
ï Read values from a Region by key using { get | getAll }
TurbineReading data = sensorData.get(new SensorKey(31415926,"2013-05-
19T19:22Z"));
ï Query values using OQL
// finds all sensor readings for the given turbine
SELECT * from /TurbineSensorData.entrySet WHERE key.turbineId = 31415926
// finds all sensor readings where the operating temp exceeds a threshold
SELECT * from /TurbineSensorData.entrySet WHERE value.operatingTemp > 120
ï Apply indexes to optimize queries
22. 22© Copyright 2015 Pivotal. All rights reserved.
Development Patterns
ï Execute functions to operate on local data in parallel
ï Respond to updates using CacheListeners and Events
ï Automatic redundancy, partitioning, distribution, consistency,
network partition detection & recovery, load balancing, âŠ
23. 23© Copyright 2015 Pivotal. All rights reserved. 23© Copyright 2015 Pivotal. All rights reserved.
Apache Geode
(incubating)
The open source core of GemFire
24. 24© Copyright 2015 Pivotal. All rights reserved.
Why OSS? Why Now? Why Apache?
ï Open Source Software is fundamentally changing buying patterns
â Developers have to endorse product selection (No longer CIO handshake)
â Community endorsement is key to product visibility
â Open source credentials attract the best developers
â Vendor credibility directly tied to street credibility of product
ï Align with the tides of history
â Customers increasingly asking to participate in product development
â Allow product development to happen with full transparency
ï Apache is where you go to build Open Source street cred
â Transparent, meritocracy which puts developers in charge
â Roman keeps shouting âApache!â every few hours
25. 25© Copyright 2015 Pivotal. All rights reserved.
Geode Will Be A Significant Apache Project
ï Over a 1000 person years invested into cutting edge R&D
ï Thousands of production customers in very demanding verticals
ï Cutting edge use cases that have shaped product thinking
ï Tens of thousands of distributed , scaled up tests that can randomize
every aspect of the product
ï A core technology team that has stayed together since founding
ï Performance differentiators that are baked into every aspect of the
product
26. 26© Copyright 2015 Pivotal. All rights reserved.
Geode or GemFire?
ï Geode is a project, GemFire is a product
ï We donated everything but the kitchen sink*
ï More code drops imminent; going forward all development
happens OSS-style (âThe Apache Wayâ)
* Multi-site WAN replication, continuous queries, and native (C/C++) client driver
30. 30© Copyright 2015 Pivotal. All rights reserved. 30© Copyright 2015 Pivotal. All rights reserved.
Geode Demo
31. 31© Copyright 2015 Pivotal. All rights reserved.
Post Region
Partitioned
People Region
Partitioned
Social Network
Person
Name: String
Description:String
Post
Id: PostId(name, date)
Text: String
32. 32© Copyright 2015 Pivotal. All rights reserved.
Partition put
Client
Server 1
Server 2
Server 3
Bucket 1
Bucket 1
Bucket 2
Bucket 2
#(LOL)=1
Put LOL
33. 33© Copyright 2015 Pivotal. All rights reserved.
Partition put
Client
Server 1
Server 2
Server 3
LOL
LOL
Bucket 2
Bucket 2
Replicate
To Secondary
34. 34© Copyright 2015 Pivotal. All rights reserved.
âUserâ Use Case â Save Objects
public interface PersonRepository extends CrudRepository<Person, String> {
}
@Autowired
PersonRepository people;
public static void main(String[] args) {
people.save(new Person(name));
posts.save(new Post(new PostId(name, date), text));
}
Nested Objects,
Compound Keys
35. 35© Copyright 2015 Pivotal. All rights reserved.
âUserâ Use Case â Save Objects
public interface PersonRepository extends CrudRepository<Person, String> {
}
@Autowired
PersonRepository people;
public static void main(String[] args) {
people.save(new Person(name));
posts.save(new Post(new PostId(name, date), text));
}
Automatically Serialized
With PDX
36. 36© Copyright 2015 Pivotal. All rights reserved.
Configuration
<gfe:partitioned-region id="people" copies="1"/>
<bean id="pdxSerializerâ
class="com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer">
<constructor-arg value="io.pivotal.happysocial.model.*"/>
</bean>
<gfe:cache pdx-serializer-ref="pdxSerializer"/>
37. 37© Copyright 2015 Pivotal. All rights reserved.
Data Analyst â Determine Sentiment
ï Find all of the posts for a user
ï Analyze their content
38. 38© Copyright 2015 Pivotal. All rights reserved.
First try â Just use a Query
public interface PostRepository extends
GemfireRepository<Post, PostId> {
@Query("select * from /posts where id.person=$1")
public Collection<Post> findPosts(String personName);
}
Collection<Post> posts = postRepository.findPosts(personName);
String sentiment = sentimentAnalyzer.analyze(posts);
39. 39© Copyright 2015 Pivotal. All rights reserved.
First try â Just use a Query
public interface PostRepository extends
GemfireRepository<Post, PostId> {
@Query("select * from /posts where id.person=$1")
public Collection<Post> findPosts(String personName);
}
Collection<Post> posts = postRepository.findPosts(personName);
String sentiment = sentimentAnalyzer.analyze(posts);
Query Nested Objects
40. 40© Copyright 2015 Pivotal. All rights reserved.
Use an Index
<gfe:index
id="postAuthor"
expression="id.person"
from="/postsâ
/>
41. 41© Copyright 2015 Pivotal. All rights reserved.
Still could be more efficient
Client
Server 1
Server 2
Server 3
Joe: LOL!!
Joe: LOL!!
EJ: arrg
Maya: Hii
Jess: sup
Jess: ok
Hitting multiple
Nodes
Bringing too much
Data to the client
42. 42© Copyright 2015 Pivotal. All rights reserved.
Colocate the data
Client
Server 1
Server 2
Server 3
Joe: LOL!! Joe: LOL!!
EJ: arrgMaya: Hii
Jess: sup Jess: ok
<gfe:partitioned-region id="posts" copies="1"
colocated-with="peopleâ>
<gfe:partition-resolver ref="partitionResolver"/>
</gfe:partitioned-region>
43. 43© Copyright 2015 Pivotal. All rights reserved.
Send behavior to data
Client
Server 1
Server 2
Server 3
Joe: LOL!! Joe: LOL!!
EJ: arrgMaya: Hii
Jess: sup Jess: ok
Execution function
getSentiment
On Joe, Jess
Execute on Joe
Execute on Jess
44. 44© Copyright 2015 Pivotal. All rights reserved.
Sample Function â Client Side
@Component
@OnRegion(region = "posts")
public interface FunctionClient {
public List<SentimentResult> getSentiment(@Filter Set<String> people);
}
45. 45© Copyright 2015 Pivotal. All rights reserved.
Sample Function â Server Side
@GemfireFunction(HA=true)
public SentimentResult getSentiment(Region<PostId, Post> localPosts,
@Filter Set<String> personNames)
throws Exception {
String personName = personNames.iterator().next();
Collection<Post> posts = localPosts.query("id.person='" personName + "'");
String sentiment = sentimentAnalyzer.analyze(posts);
return new SentimentResult(sentiment, personName);
}
46. 46© Copyright 2015 Pivotal. All rights reserved.
Sample Function â Server Side
@GemfireFunction(HA=true)
public SentimentResult getSentiment(Region<PostId, Post> localPosts,
@Filter Set<String> personNames)
throws Exception {
String personName = personNames.iterator().next();
Collection<Post> posts = localPosts.query("id.person='" personName + "'");
String sentiment = sentimentAnalyzer.analyze(posts);
return new SentimentResult(sentiment, personName);
}
47. 47© Copyright 2015 Pivotal. All rights reserved.
Sample Function â Server Side
@GemfireFunction(HA=true)
public SentimentResult getSentiment(Region<PostId, Post> localPosts,
@Filter Set<String> personNames)
throws Exception {
String personName = personNames.iterator().next();
Collection<Post> posts = localPosts.query("id.person='" personName + "'");
String sentiment = sentimentAnalyzer.analyze(posts);
return new SentimentResult(sentiment, personName);
}
48. 48© Copyright 2015 Pivotal. All rights reserved. 48© Copyright 2015 Pivotal. All rights reserved.
Demo
49. 49© Copyright 2015 Pivotal. All rights reserved. 49© Copyright 2015 Pivotal. All rights reserved.
Design
âą Persistence
âą PDX Serialization
50. 50© Copyright 2015 Pivotal. All rights reserved.
Persistence â Design Goals
ï High availability
ï Low latency, high throughput
ï Durability
ï Minimal impact to in memory speed
â Minimize IO operations
â Minimize locking
â Minimize deserialization
51. 51© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 3Server 2
Bucket 3
*primary*
Bucket 1
secondary
Bucket 3
secondary
Bucket 2
*primary*
Server 1
Bucket 2
secondary
Bucket 1
*primary*
52. 52© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 1 Server 3Server 2
Bucket 2
secondary
Bucket 1
*primary*
Bucket 3
*primary*
Bucket 1
secondary
Bucket 3
secondary
Bucket 2
*primary*
What if a server
crashes?
53. 53© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 1 Server 3Server 2
Bucket 2
secondary
Bucket 1
*primary*
Bucket 3
*primary*
Bucket 1
*primary*
Bucket 3
secondary
Bucket 2
*primary*
Bucket 2
secondary
Primary
Failover
Restore
Redundancy
Bucket 1
secondary
54. 54© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 1 Server 3Server 2
Bucket 2
secondary
Bucket 1
*primary*
Bucket 3
*primary*
Bucket 1
*primary*
Bucket 3
secondary
Bucket 2
*primary*
Bucket 2
secondary
Bucket 1
secondary
What if they all crash?
55. 55© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 3Server 2
Bucket 3
*primary*
Bucket 1
*primary*
Bucket 3
secondary
Bucket 2
*primary*
Bucket 2
secondary
Bucket 1
secondary
Server 1
Bucket 2
secondary
Bucket 1
*primary*
Compare Persistent View
On Restart
56. 56© Copyright 2015 Pivotal. All rights reserved.
Persistence â Shared Nothing
Server 1
Bucket 2
secondary
Bucket 1
*primary*
Server 3Server 2
Bucket 3
*primary*
Bucket 1
secondary
Bucket 3
secondary
Bucket 2
*primary*
Bucket 2
secondary
Bucket 1
secondary
Recover Latest
Data &
Rebalance
57. 57© Copyright 2015 Pivotal. All rights reserved.
Modify
k1->v5
Create
k6->v6
Create
k1->v1
Create
k2->v2
Modify
k1->v3
Create
k4->v4
Modify
k1->v5
Create
k6->v6
Member
1
Persistence - Operation Logs
Put k6->v6
Oplog2.crf
Oplog1.crf
Append to
operation log
58. 58© Copyright 2015 Pivotal. All rights reserved.
Modify
k1->v5
Create
k6->v6
Create
k1->v1
Modify
k1->v3
Member
1
Persistence - Compaction
Oplog2.crf
Oplog1.crf
Create
k2->v2
Create
k4->v4
Copy live
data forward
59. 59© Copyright 2015 Pivotal. All rights reserved.
Modify
k1->v5
Create
k6->v6
Persistence - Compaction
Create
k2->v2
Create
k4->v4
Oplog2.crf
Member
1
Modify
k4->v7Oplog3.crf
Put k4->v7
60. 60© Copyright 2015 Pivotal. All rights reserved. 60© Copyright 2013 Pivotal. All rights reserved.
Design
âą Persistence
âą PDX Serialization
61. 61© Copyright 2015 Pivotal. All rights reserved.
Fixed or flexible schema?
id name age pet_id
{
id : 1,
name : âFredâ,
age : 42,
pet : {
name : âBarneyâ,
type : âdinoâ
}
}
OR
62. 62© Copyright 2015 Pivotal. All rights reserved.
But how to serialize data?
http://blog.pivotal.io/pivotal/products/data-serialization-how-to-run-multiple-big-data-apps-at-once-with-gemfire
63. 63© Copyright 2015 Pivotal. All rights reserved.
Portable Data eXchange
C#, C++, Java, JSON
| header | data |
| pdx | length | dsid | typeId | fields | offsets |
64. 64© Copyright 2015 Pivotal. All rights reserved.
Efficient for queries
SELECT p.name from /Person p WHERE p.pet.type = âdinoâ
{
id : 1,
name : âFredâ,
age : 42,
pet : {
name : âBarneyâ,
type : âdinoâ
}
}
single field
deserialization
65. 65© Copyright 2015 Pivotal. All rights reserved.
Easy to use
ï Access from Java, C#, C++, JSON
ï Domain objects not required
ï Automatic type definition
â No IDL compiler or schema required
â No hand-coded read/write methods
66. 66© Copyright 2015 Pivotal. All rights reserved.
Distributed type registry
Member A Member B
Distributed Type Definitions
Person p1 = âŠ
region.put(âFredâ, p1);
67. 67© Copyright 2015 Pivotal. All rights reserved.
Distributed type registry
Member A Member B
Distributed Type Definitions
Person p1 = âŠ
region.put(âFredâ, p1);
automatic
definition
68. 68© Copyright 2015 Pivotal. All rights reserved.
Distributed type registry
Member A Member B
Distributed Type Definitions
Person p1 = âŠ
region.put(âFredâ, p1);
automatic
definition
69. 69© Copyright 2015 Pivotal. All rights reserved.
Distributed type registry
Member A Member B
Distributed Type Definitions
Person p1 = âŠ
region.put(âFredâ, p1);
automatic
definition
replicate serialized data
containing typeId
70. 70© Copyright 2015 Pivotal. All rights reserved.
Schema evolution
PDX provides forwards and backwards
compatibility, no code required
Member A Member B
Distributed Type Definitions
v
1
v
2
Application
#2
Application
#1
v2 objects preserve data
from missing fields
v1 objects use default values
to fill in new fields
71. 71© Copyright 2015 Pivotal. All rights reserved.
Questions?
ï http://geode.incubator.apache.org
ï dev@geode.incubator.apache.org
ï user@geode.incubator.apache.org
ï http://github.com/apache/incubator-geode
72. 72© Copyright 2015 Pivotal. All rights reserved. 72© Copyright 2013 Pivotal. All rights reserved.
Bonus Content
73. 73© Copyright 2015 Pivotal. All rights reserved. 73© Copyright 2015 Pivotal. All rights reserved.
Design
âą Persistence
âą Asynchronous Events
âą Client Subscriptions
âą PDX Serialization
74. 74© Copyright 2015 Pivotal. All rights reserved.
Asynchronous Events â Design Goals
ï High availability
ï Low latency, high throughput
ï Deliver events to a receiver without impacting the write path
75. 75© Copyright 2015 Pivotal. All rights reserved.
Member 3
Member 1
Serial Queues
Member 2
LOL!!put
Primary Queue
Secondary Queue
Enqueue
sup
LOL!!
sup
sup
LOL!!
Replicate
76. 76© Copyright 2015 Pivotal. All rights reserved.
Member 3
Member 1
Member 2
Serial Queues
sup
LOL!!
sup
LOL!!
AsyncEventListener
{
processBatch()
}
LOL!!
sup
Dispatch Events
from Primary
77. 77© Copyright 2015 Pivotal. All rights reserved.
put
Secondary Queue
(Partition 1)
LOL!!
sup
sup
LOL!!
Primary Queue
(Partition 2)
Parallel Queues
Primary Queue
(Partition 1)
LOL!!
sup
sup
LOL!!
Word
Word
78. 78© Copyright 2015 Pivotal. All rights reserved.
LOL!!
sup
sup
LOL!!
Parallel Queues
LOL!!
sup
sup
LOL!!
Word
Word
AsyncEventListener
{
processBatch()
}
AsyncEventListener
{
processBatch()
}
Parallel
Dispatch
79. 79© Copyright 2015 Pivotal. All rights reserved. 79© Copyright 2013 Pivotal. All rights reserved.
Design
âą Persistence
âą Asynchronous Events
âą Client Subscriptions
âą PDX Serialization
80. 80© Copyright 2015 Pivotal. All rights reserved.
âThere are only two hard things in Computer Science: cache
invalidation, naming things, and off-by-one errors.â
â the internet
81. 81© Copyright 2015 Pivotal. All rights reserved.
Client driver
ï Intelligent â understands data distribution for single hop
network access
ï Caching â can be configured to locally cache data for even
faster access
ï Events â registerInterest() in keys to receive push
notifications
82. 82© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
ï Useful for refreshing client cache, pushing events (âtopicsâ)
to multiple clients
ï Highly available & scalable via in-memory replicated queues
ï Events are ordered, at-least-once delivery
ï Durable subscriptions, conflation optional
83. 83© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
Member A Member B
region.registerInterest(âFredâ);
Client
Client
84. 84© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
Member A Member B
Person p1 = âŠ
region.put(âFredâ, p1);
region.registerInterest(âFredâ);
Client
Client
85. 85© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
Member A Member B
Person p1 = âŠ
region.put(âFredâ, p1);
region.registerInterest(âFredâ);
Client
Client
86. 86© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
Member A Member B
Person p1 = âŠ
region.put(âFredâ, p1);
region.registerInterest(âFredâ);
Client
Client
87. 87© Copyright 2015 Pivotal. All rights reserved.
Client subscriptions
Member A Member B
Person p1 = âŠ
region.put(âFredâ, p1);
region.registerInterest(âFredâ);
Client
Client