Amazon ElastiCache is a web service that makes it easy to deploy, operate, and scale an in-memory data store or cache in the cloud. The service improves the performance of web applications by allowing you to retrieve information from fast, managed, in-memory data stores, instead of relying entirely on slower disk-based databases. In this tech talk, we’ll provide a peek behind the scenes to learn about Amazon ElastiCache's design and architecture. You’ll see common design patterns with our Redis and Memcached offerings and how customers have used them for in-memory operations to reduce latency and improve application throughput. During this session, we review ElastiCache best practices, design patterns, and anti-patterns.
Learning Objectives:
- Learn how to integrate Amazon ElastiCache in your workloads
- Understand the benefits of an In-Memory data store
- Learn how to apply various caching strategies in your applications
- Hands on demonstration using Amazon ElastiCache
2. Learning Objectives
§ Learn how to integrate Amazon ElastiCache in your workloads
§ Understand the benefits of an In-Memory data store
§ Learn how to apply various caching strategies in your
applications
§ Hands on demonstration using Amazon ElastiCache
2
3. In-Memory Key-Value NoSQL Store
High-performance
Redis and Memcached
Fully managed; Zero admin
Highly Available and Reliable
Hardened by Amazon
Amazon
ElastiCache
4. Redis – The In-Memory Leader
Powerful
~200 commands + Lua scripting
In-memory data structure server
Utility data structures
strings, lists, hashes, sets, sorted
sets, bitmaps & HyperLogLogs
Simple
Atomic operations
supports transactions
Ridiculously fast!
<1ms latency for most commands
Highly Available
replication
Persistence
Open Source
6. Redis Data Types - String
• Binary safe.
• Can contain a max value of 512 MB.
• Great for storing Counters, HTML, Images, JSON objects, etc.
valueKey
7. Key
Redis Data Types - Set
• A collection of unique unordered Strings values
• Great for Deduplicating and Grouping related information
• Can union, intersect and find differences between other SETS
value: 75 value: 1 value: 39 value: 63 value: 63
Duplicate!
value: 63
8. Key
Redis Data Types - Sorted Set
• A collection of unique Strings values ordered by score
• Great for Deduplication, Grouping and Sorting related information
• Get specific range and rank of elements based on score
value: mike
score: 50 score: 75
value: dan value: emma
score: 79
value: lina
score: 123
value: luke
score: 350
9. Key
Redis Data Types - List
HEAD value 1 value 2 value 3 TAIL
• A collection of Strings stored in the order of their insertion
• Push and Pop from head or tail of the list or insert at specific value position
• Great for message queues and timelines
10. Key
Redis Data Types - Hashes
Field 1 value 1
• A collection of unordered fields and values
• Great for representing objects
• Ability to Add, GET, and DEL individual fields by Key
Field 2 value 2
Field 3 value 3
Field 4 value 4
11. Redis Data Types & More!
Run Lua scripts Geospatial Queries! Pub / Sub
13. Amazon
ElastiCache
Redis Multi-AZ with Automatic Failover
Open-Source Compatible
Fully Managed
Enhanced Redis Engine
Easy to Deploy, Use and Monitor
No Cross-AZ Data Transfer Costs
Extreme Performance at Cloud Scale
ElastiCache - Customer Value
16. Caching
# Write Through
def save_user(user_id, values):
record = db.query("update users ... where id = ?", user_id, values)
cache.set(user_id, record, 300) # TTL
return record
# Lazy Load
def get_user(user_id):
record = cache.get(user_id)
if record is None:
record = db.query("select * from users where id = ?", user_id)
cache.set(user_id, record, 300) # TTL
return record
# App code
save_user(17, {"name": “Big Mike"})
user = get_user(17)
Amazon
ElastiCache
17. Caching
# Write Through
def save_user(user_id, values):
record = db.query("update users ... where id = ?", user_id, values)
cache.set(user_id, record, 300) # TTL
return record
# Lazy Load
def get_user(user_id):
record = cache.get(user_id)
if record is None:
record = db.query("select * from users where id = ?", user_id)
cache.set(user_id, record, 300) # TTL
return record
# App code
save_user(17, {"name": “Big Mike"})
user = get_user(17)
Amazon
ElastiCache
Write Through
1. Updated DB
2. SET in Cache
Lazy Load
1. GET from cache.
2. If MISS get from DB
3. Then SET in Cache
18. 1) Install php, apache php memcache client
e.g. yum install php apache php-pecl-memcache
2) Configure “php.ini”
session.save_handler = memcache
session.save_path=
"tcp://node1:11211, tcp://node2:11211"
3) Configure “php.d/memcache.ini”
memcache.hash_strategy = consistent
memcache.allow_failover = 1
memcache.session_redundancy=3*
4) Restart httpd
5) Begin using Session Data:
Auto Scaling group
For situations where you need an
external session store
• Especially needed when using ASGs
• Cache is optimal for high-volume
reads
PHP Example
Session Caching
https://github.com/mikelabib/elasticache-memcached-php-demo
19. IoT Device Data
AWS
IoT
AWS
IoT Device
Amazon
EC2
AWS
Lambda
Hot Data
Amazon
DynamoDB
Longer
Retention
Data Lake
Amazon
S3
Amazon
Glacier
Cold Data
Amazon
Kinesis
Firehose
Amazon
ElastiCache
26. Features
• Horizontal Scale of up to 3.5 TiB per cluster
• Up to 20 million reads per second
• Up to 4.5 million writes per second
• Enhanced Redis Engine within ElastiCache
• Up to 4x times failover than with Redis 2.8
• Cluster-level Backup and Restore
• Fully Supported by AWS CloudFormation
• Ability to resize your cluster
• Available in all AWS Regions
Redis 3.2 Support
Amazon
ElastiCache
34. Availability Zone A
slots 0 - 5454 slots 5455 – 10909
Redis Cluster
slots 10910 – 16363
Availability Zone B Availability Zone C
slots 5455 – 10909 slots 5455 – 10909slots 0 - 5454 slots 0 - 5454
slots 10910 – 16363 slots 10910 – 16363
Scenario 1: Single Primary Shard Failure
35. Availability Zone A
slots 0 - 5454 slots 5455 – 10909
Redis Cluster
Scenario 1: Single Primary Shard Failure
slots 10910 – 16363
Availability Zone B Availability Zone C
slots 5455 – 10909 slots 5455 – 10909slots 0 - 5454 slots 0 - 5454
slots 10910 – 16363
Mitigation:
1. Promote Read Replica Node (~15-30s)
2. Repair Failed Node
slots 10910 – 16363
36. Availability Zone A
slots 0 - 5454 slots 5455 – 10909
Redis Cluster
Scenario 2: Majority of Primary Shards Fail
slots 10910 – 16363
Availability Zone B Availability Zone C
slots 5455 – 10909 slots 5455 – 10909slots 0 - 5454 slots 0 - 5454
slots 10910 – 16363slots 10910 – 16363
37. Availability Zone A
slots 0 - 5454 slots 5455 – 10909
Redis Cluster
slots 10910 – 16363
Availability Zone B Availability Zone C
slots 5455 – 10909 slots 5455 – 10909slots 0 - 5454 slots 0 - 5454
Mitigation: Redis enhancements on ElastiCache
• Promote Read Replica Nodes
• Repair Failed Nodes
slots 10910 – 16363slots 10910 – 16363
Scenario 2: Majority of Primary Shards Fail
38. How do I migrate from a non-clustered Redis
environment to a clustered Redis environment
on ElastiCache?
39. Migrating to a Cluster
1. Create new Cluster
2. Make snapshot of old CacheCluster
3. Restore snapshot to new Cluster
4. Update Client
5. Terminate old Cluster
S5
S1
S2
S4 S3
Client
Old
< 3.2
Client
40. How do change the number of Redis Shards I
have allocated?
41. 1. Create new Cluster
2. Make snapshot of old CacheCluster
3. Restore snapshot to new Cluster
4. Terminate old Cluster
Resizing your Cluster
42. Architecting for Availability
• Upgrade to the latest engine version – 3.2.4
• Use Newer Instance types when possible (e.g. M4 vs M3)
• Set reserved-memory to 30% of total available memory
• Swap usage should be zero or very low. Scale if not.
• Put read-replicas in a different AZ from the primary
• For important workloads use 2 read replicas per primary
• Write to the primary, read from the read-replicas
• Take snapshots from read-replicas to support your RPO
• For Redis Cluster have odd number of shards.
44. Key ElastiCache CloudWatch Metrics
• CPUUtilization
• Memcached – up to 90% ok
• Redis – divide by cores (ex: 90% / 4 = 22.5%)
• SwapUsage low
• CacheMisses / CacheHits Ratio low / stable
• Evictions near zero
• Exception: Russian doll caching
• CurrConnections stable
• Setup alarms with CloudWatch Metrics
• Whitepaper: http://bit.ly/elasticache-whitepaper
45. ElastiCache Modifiable Parameters
• Maxclients: 65000 (unchangeable)
• Use connection pooling
• timeout – Closes a connection after its been idle for a given interval
• tcp-keepalive – Detects dead peers given an interval
• Databases: 16 (Default) for non-clustered mode
• Logical partition
• Reserved-memory: 0 (Default)
• Recommended
§ 50% of maxmemory to use before 2.8.22
§ 30% after 2.8.22 – ElastiCache
• Maxmemory-policy:
• The eviction policy for keys when maximum memory usage is reached
• Possible values: volatile-lru, allkeys-lru, volatile-random, allkeys-random,
volatile-ttl, noeviction
47. Java App Java App
Web Server Web Server
Database Cache
Customers
AZ1 AZ2
Distributed
Cache
Demo workload topology: Customer Data
CustomerDB Primary CustomerDB Standby
48. Caching Strategies
1. Cache Database SQL ResultSet (Row)
PRO
When data retrieval logic is abstracted from the code consuming the ResultSet, caching the ROW can
be extremely effective and can be implemented against any RDBMS.
CON
Data retrieval still requires extracting values from the ROW and does not further simplify data access;
It only reduces data retrieval latency.
SELECT * FROM x WHERE y
ID First_Name Last_Name City
123Michael Labib Chicago
ResultSet Object (ROW) Key: Query, Value: CRS as byte array
49. Caching Strategies
2. Cache database values into custom format in a Redis String
SELECT * FROM x WHERE y
ID First_Name Last_Name City
123Michael Labib Chicago
Key: 123, Value: firstNameString firstName = rs.getString(First_Name)
PRO
Very easy to implement. Cache any desired database fields and values into a Redis String. For example,
store your retrieved data into a JSON object stored in a Redis String.
CON
Minor. Application code will leverage different types of Objects when retrieving data (i.e. Redis data
structures and database results when needed)
50. Caching Strategies
3. Cache serialized application object (e.g. Java Object )
SELECT * FROM x WHERE y
ID First_Name Last_Name City
123Michael Labib Chicago
Key: CUSTOMER_ID:123,
Value: Customer Object as byte array
String firstName = rs.getString(First_Name);
customer.setFirstName(firstName);
String lastName = rs.getString(Last_Name);
customer.setLastName(lastName);
PRO
Utilize application objects in their native structure and data state when serialized.
CON
Advanced application development use case.
51. Caching Strategies
4. Leverage advanced Redis Data Structures for cached data
SELECT * FROM x WHERE y
ID First_Name Last_Name City
123Michael Labib Chicago
Key: CUSTOMER_ID:123, Value: rsHash
String firstName = rs.getString(First_Name);
rsHash.put(“firstName", firstName);
String lastName = rs.getString(Last_Name);
rsHash.put(“lastName", lastName);
jedis.hmset(“CUSTOMER_ID:123", rsHash);
PRO
In addition to reducing data retrieval latency, cache data into specific data structure that simplifies the
data access pattern.
CON
Minor. Application code will leverage different types of objects when retrieving data (i.e. Redis data
structures and database results when needed)
52. Demo Steps: Database Setup
• Create CustomerDB with Database of choice
• Load sample data
• Create sample or use mock tool https://www.mockaroo.com/
• Set appropriate security groups to grant access to EC2 SGs hosting your applications
• Enable port 3306 for your IP to use DB editor for convenience
CREATE table Customer (
CUSTOMER_ID INT
,FIRST_NAME VARCHAR(50)
,LAST_NAME VARCHAR(50)
,EMAIL VARCHAR(50)
,GENDER VARCHAR(50)
,CITY VARCHAR(50)
,STATE VARCHAR(50)
,ADDRESS VARCHAR(50)
,COUNTRY VARCHAR(50) );
INSERT into Customer (CUSTOMER_ID, FIRST_NAME, LAST_NAME, EMAIL, GENDER, CITY, STATE, ADDRESS, COUNTRY)
VALUES (1, 'Maria', 'Rodriguez', 'mrodriguez0@bbb.org', 'Female', 'Dallas', 'Texas', '63 8th Circle', 'United States');
53. Demo Steps: ElastiCache & EC2 Setup
• Create ElastiCache for Redis Cluster
• Test connectivity from EC2
• Set appropriate security groups to grant access to EC2 SGs hosting your applications
• Install Redis Client on the EC2 instances to command line Redis access
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make && make install
src/redis-cli -h your-elasticache-redis-endpoint -p 6379
54. Demo: Example Java application
uses
uses
implements
implements
<<interface>>
<<interface>>
DAO Pattern
uses
<<interface>>
uses
55. Demo: Data retrieval logic
Data retrieval details abstracted from consuming applications
1. Check cache first for requested data
2. If not available, retrieve the data from origin database
3. Cache any data not available previously set in cache for 5
minutes
4. Return results
https://github.com/mikelabib/amazon-elasticache-redis-caching-demos
Demo
56. Summary
§ Caching your data can greatly improve your data retrieval
speeds
§ There are various strategies you can implement to cache
your data, use the one that meets your needs
§ Caching your data can also greatly reduce your database
costs when architecting for scale
56