SlideShare ist ein Scribd-Unternehmen logo
1 von 88
Downloaden Sie, um offline zu lesen
Handling 20 billion
requests a month? Easy
Dmitriy Dumanskiy
Cogniance, mGage project
Java Team Lead
Java blog : habrahabr.ru/users/doom369/topics
Project evolution
Ad Project 1
Ad Project 2
XXXX
Ad Project 1 delivery load
3 billions req/mon.
~8 c3.xLarge Amazon instances.
Average load : 2400 req/sec
Peak : x10
Ad Project 2 delivery load
14 billions req/mon.
~16 c3.xLarge Amazon
instances.
Average load : 6000 req/sec
Peak : x6
XXXX delivery Load
20 billions req/mon.
~14 c3.xLarge Amazon instances.
Average load : 11000 req/sec
Peak : x6
Is it a lot?
Average load : 11000 req/sec
Twitter : new tweets
15 billions a month
Average load : 5700 req/sec
Peak : x30
Delivery load
Requests per
month
Max load
per
instance,
req/sec
Requirements
Servers,
AWS c3.
xLarge
Ad Project 1 3 billions 300
HTTP
Time 95% < 60ms
8
Ad Project 2 14 billions 400
HTTP
Time 95% < 100ms
16
XXXX 20 billions 800
HTTPS
Time 99% < 100ms
14
Delivery load
c3.XLarge - 4 vCPU, 2.8 GHz Intel Xeon E5-2680
LA - ~2-3
1-2 cores reserved for sudden peaks
BE tech stacks
Ad Project 2:
Spring, iBatis, MySql, Solr, Vertica, Cascading, Tomcat
Ad Project 1 :
Spring, Hibernate, Postgres, Distributed ehCache, Hadoop, Voldemort, Jboss
XXXX:
Spring, Hibernate, MySQL, Solr, Cascading, Redis, Tomcat
Real problem
● ~85 mln active users, ~115 mln registered users
● 11.5 messages per user per day
● ~11000 req/sec
● Peaks 6x
● 99% HTTPS with response time < 100ms
● Reliable and scalable for future grow up to 80k
Architecture
AdServer Console (UI)
Reporting
Architecture
Console (UI)
MySql
SOLR Master
SOLR Slave SOLR SlaveSOLR Slave
SOLR? Why?
● Pros:
○ Quick search on complex queries
○ Has a lot of build-in features (push-
notifications, master-slave replication,
RDBMS integration)
● Cons:
○ Only HTTP, embedded performs worth
○ Not easy for beginners
○ Max load is ~100 req/sec per instance
“Simple” query
"-(-connectionTypes:"+"""+getConnectionType()+"""+" AND connectionTypes:[* TO
*]) AND "+"-connectionTypeExcludes:"+"""+getConnectionType()+"""+" AND " + "-(-
OSes:"+"(""+osQuery+"" OR ""+getOS()+"")"+" AND OSes:[* TO *]) AND " + "-
osExcludes:"+"(""+osQuery+"" OR ""+getOS()+"")" "AND (runOfNetwork:T OR
appIncludes:"+getAppId()+" OR pubIncludes:"+getPubId()+" OR categories:
("+categoryList+"))" +" AND -appExcludes:"+getAppId()+" AND -pubExcludes:"
+getPubId()+" AND -categoryExcludes:("+categoryList+") AND " + keywordQuery+" AND
" + "-(-devices:"+"""+getHandsetNormalized()+"""+" AND devices:[* TO *]) AND " +
"-deviceExcludes:"+"""+getHandsetNormalized()+"""+" AND " + "-(-carriers:"+"""
+getCarrier()+"""+" AND carriers:[* TO *]) AND " + "-carrierExcludes:"+"""
+getCarrier()+"""+" AND " + "-(-locales:"+"(""+locale+"" OR ""+langOnly+"")"
+" AND locales:[* TO *]) AND " + "-localeExcludes:"+"(""+locale+"" OR ""
+langOnly+"") AND " + "-(-segments:("+segmentQuery+") AND segments:[* TO *]) AND
" + "-segmentExcludes:("+segmentQuery+")" + " AND -(-geos:"+geoQuery+" AND geos:[*
TO *]) AND " + "-geosExcludes:"+geoQuery
Solr
Index size < 1 Gb - response time 20-30 ms
Index size < 100 Gb - response time 1-2 sec
Index size < 400 Gb - response time from 10
secs
Architecture
MySql
Solr Master
SOLR Slave
AdServer
SOLR Slave
AdServer
SOLR Slave
AdServer
No-SQL
AdServer - Solr Slave
Delivery:
volatile DeliveryData cache;
Cron Job:
DeliveryData tempCache = loadData();
cache = tempCache;
Why no-sql?
● Realtime data
● Quick response time
● Simple queries by key
● 1-2 queries to no-sql on every request. Average load
10-20k req/sec and >120k req/sec in peaks.
● Cheap solution
Why Redis? Pros
● Easy and light-weight
● Low latency and response time.
99% is < 1ms. Average latency is ~0.2ms
● Up to 100k 'get' commands per second on
c1.X-Large
● Cool features (atomic increments, sets,
hashes)
● Ready AWS service — ElastiCache
Why Redis? Cons
● Single-threaded from the box
● Utilize all cores - sharding/clustering
● Scaling/failover not easy
● Limited up to max instance memory (240GB largest
AWS)
● Persistence/swapping may delay response
● Cluster solution not production ready
● Data loss possible
DynamoDB vs Redis
Price per month Put, 95% Get, 95% Rec/sec
DynamoDB 58$ 300ms 150ms 50
DynamoDB 580$ 60ms 8ms 780
DynamoDB 5800$ 16ms 8ms 1250
Redis 200$ (c1.medium) 3ms <1ms 4000
ElastiCache 600$ (c1.xlarge) <1ms <1ms 10000
What about others?
● Cassandra
● Voldemort
● Memcached
Redis RAM problem
● 1 user entry ~ from 80 bytes to 3kb
● ~85 mln users
● Required RAM ~ from 1 GB to 300 GB
Data compression
Json → Kryo binary → 4x times less data →
Gzipping → 2x times less data == 8x less data
Now we need < 40 GB
+ Less load on network stack
AdServer BE
Average response time — ~1.2 ms
Load — 800 req/sec with LA ~4
c3.XLarge == 4 vCPU
AdServer BE
● Logging — 12% of time (5% on SSD);
● Response generation — 15% of time;
● Redis request — 50% of time;
● All business logic — 23% of time;
Reporting
AdServer Hadoop ETL
MySQLConsole
S3 S3
Delivery logs Aggregated logs
1 hour batch
Delivery log structure
{ "uid":"test",
"platform":"android",
"app":"xxx",
"ts":1375952275223,
"pid":1,
"education":"Some-Highschool-or-less",
"type":"new",
"sh":1280,
"appver":"6.4.34",
"country":"AU",
"time":"Sat, 03 August 2013 10:30:39 +0200",
"deviceGroup":7,
"rid":"fc389d966438478e9554ed15d27713f51",
"responseCode":200,
"event":"ad",
"device":"N95",
"sw":768,
"ageGroup":"18-24",
"preferences":["beer","girls"] }
Log structure
● 1 mln. records == 0.6 GB.
● ~900 mln records a day == ~0.55 TB.
● 1 month up to 20 TB of data.
● Zipped data is 10 times less.
Reporting
Customer : “And we need fancy reporting”
But 20 TB of data per month is huge. So what
we can do?
Reporting
Dimensions:
device, os, osVer, sreenWidth, screenHeight,
country, region, city, carrier, advertisingId,
preferences, gender, age, income, sector,
company, language, etc...
Use case:
I want to know how many users saw my ad in San-
Francisco.
Reporting
Geo table:
Country, City, Region, CampaignId, Date, counters;
Device table:
Device, Carrier, Platform, CampaignId, Date, counters;
Uniques table:
CampaignId, UID
Predefined report types → aggregation by
predefined dimensions → 500-1000 times less
data
20 TB per month → 40 GB per month
Of course - hadoop
● Pros:
○ Unlimited (depends) horizontal scaling
● Cons:
○ Not real-time
○ Processing time directly depends on quality code
and on infrastructure cost.
○ Not all input can be scaled
○ Cluster startup is so... long
Timing
● Hadoop (cascading) :
○ 25 GB in peak hour takes ~40min (-10 min). CSV
output 300MB. With cluster of 4 c3.xLarge.
● MySQL:
○ Put 300MB in DB with insert statements ~40 min.
Timing
● Hadoop (cascading) :
○ 25 GB in peak hour takes ~40min (-10 min). CSV
output 300MB. With cluster of 4 c3.xLarge.
● MySQL:
○ Put 300MB in DB with insert statements ~40 min.
● MySQL:
○ Put 300MB in DB with optimizations ~5 min.
Optimized are
● No “insert into”. Only “load data” - ~10 times faster
● “ENGINE=MyISAM“ vs “INNODB” when possible - ~5
times faster
● For “upsert” - temp table with “ENGINE=MEMORY” - IO
savings
Cascading
Hadoop:
void map(K key, V val,
OutputCollector collector) {
...
}
void reduce(K key, Iterator<V> vals,
OutputCollector collector) {
...
}
Cascading:
Scheme sinkScheme = new TextLine(new Fields(
"word", "count"));
Pipe assembly = new Pipe("wordcount");
assembly = new Each(assembly, new Fields( "line"
), new RegexGenerator(new Fields("word"), ",") );
assembly = new GroupBy(assembly, new Fields(
"word"));
Aggregator count = new Count(new Fields(
"count"));
assembly = new Every(assembly, count);
Why cascading?
Hadoop Job 1
Hadoop Job 2
Hadoop Job 3
Result of one job should be processed by another job
Lessons Learned
Facts
● HTTP x2 faster HTTPS
● HTTPS keep-alive +80% performance
● Java 7 40% faster Java 6 (our case)
● All IO operations minimized
● Less OOP - better performance
Cost of IO
L1 cache 3 cycles
L2 cache 14 cycles
RAM 250 cycles
Disk 41 000 000 cycles
Network 240 000 000 cycles
Cost of IO
@Cacheable is everywhere
Java 7. Random
return items.get(new Random().nextInt(items.size()))
Java 7. Random
return items.get(ThreadLocalRandom().current().nextInt(items.
size()))
~3x
Java 7. Less garbage
new ArrayList():
this.elementData = {};
insteadOf
this.elementData = new Object
[10];
new HashMap():
Entry<K,V>[] table = {};
insteadOf
this.table = new Entry[16];
Java 7. Less garbage
Before:
class String {
int offset;
int count;
char value[];
int hash;
}
After:
class String {
char value[];
int hash;
}
Java 7. GC
200mb per second - 0.5% CPU time
Smaller heap - better performance
Java 7. String
● Substring
● Split
Use latest versions
Jedis 2.2.3 uses commons-pool 1.6
Jedis 2.3 uses commons-pool 2.0
commons-pool 2.0 - ~2x times faster
Small tweaks. Date
new Date()
vs
System.currentTimeMillis()
Small tweaks. SimpleDateFormat
return new SimpleDateFormat(“MMM yyyy HH:mm:ss Z”).parse
(dateString)
Small tweaks. SimpleDateFormat
● ThreadLocal
● Joda - threadsafe DateTimeFormat
Small tweaks. Pattern
public Item isValid(String ip) {
Pattern pattern = Pattern.compile("xxx");
Matcher matcher = pattern.matcher(ip);
return matcher.matches();
}
Small tweaks. Pattern
final Pattern pattern = Pattern.compile("xxx");
final Matcher matcher = pattern.matcher(“”);
public Item isValid(String ip) {
matcher.reset(ip);
return matcher.matches();
}
Small tweaks. String.split
item.getPreferences().split(“[_,;,-]”);
Small tweaks. String.split
item.getPreferences().split(“[_,;,-]”);
vs
static final Pattern PATTERN = Pattern.compile("[_,;,-]");
PATTERN.split(item.getPreferences()) - ~2x faster
vs
custom code - up to 5x faster
Small tweaks. FOR loop
for (A a : arrayListA) {
// do something
for (B b : arrayListB) {
// do something
for (C c : arrayListC) {
// do something
}
}
}
Small tweaks. FOR loop
for (Iterator<A> i = arrayListA.iterator(); i.hasNext();) {
a = i.next();
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
}
Small tweaks. FOR loop
Small tweaks. LinkedList
Just don’t use it
Small tweaks. Primitives
double coord = Double.valueOf(textLine);
Avoid concurrency
volatile the simplest way
Avoid concurrency
JedisPool.getResource() - sync
JedisPool.returnResource() - sync
OutputStreamWriter.write() - sync
UUID.randomUUID() - sync
Avoid concurrency
JedisPool.getResource()
JedisPool.returnResource()
replace with
ThreadLocal<JedisConnection>
Avoid concurrency
ThreadLocal<JedisConnection> - requires
~1000 open connections for Redis.
More connections — slower redis response.
Dead end.
Avoid concurrency
OutputStreamWriter.write()
● No flush() on every request and big buffered writer
● Async writer
No guarantee for no data loss.
Dead end.
Avoid concurrency
OutputStreamWriter.write()
Or buy SSD =)
+30-60% on disk IO
Hadoop
Map input : 300 MB
Map output : 80 GB
Hadoop
● mapreduce.map.output.compress = true
● codecs: GZip, BZ2 - CPU intensive
● codecs: LZO, Snappy
● codecs: JNI
~x10
Hadoop
Consider Combiner
Hadoop
Text, IntWritable, BytesWritable, NullWritable,
etc
Simpler - better
Hadoop
map(T value, ...) {
Log log = parse(value);
Data data = dbWrapper.getSomeMissingData(log.getCampId());
}
Hadoop
Missing data:
map(T value, ...) {
Log log = parse(value);
Data data = dbWrapper.getSomeMissingData(log.getCampId());
}
Wrong
Hadoop
map(T value, ...) {
Log log = parse(value);
Key resultKey = makeKey(log.getCampName(), ...);
output.collect(resultKey, resultValue);
}
Hadoop
Unnecessary data:
map(T value, ...) {
Log log = parse(value);
Key resultKey = makeKey(log.getCampName(), ...);
output.collect(resultKey, resultValue);
}
Wrong
Hadoop
RecordWriter.write(K key, V value) {
Entity entity = makeEntity(key, value);
dbWrapper.save(entity);
}
Hadoop
Minimize IO:
RecordWriter.write(K key, V value) {
Entity entity = makeEntity(key, value);
dbWrapper.save(entity);
}
Wrong
Hadoop
public boolean equals(Object obj) {
EqualsBuilder equalsBuilder = new EqualsBuilder();
equalsBuilder.append(id, otherKey.getId());
...
}
public int hashCode() {
HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
hashCodeBuilder.append(id);
...
}
Hadoop
public boolean equals(Object obj) {
EqualsBuilder equalsBuilder = new EqualsBuilder();
equalsBuilder.append(id, otherKey.getId());
...
}
public int hashCode() {
HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
hashCodeBuilder.append(id);
...
}
Wrong
Hadoop
public void map(...) {
…
for (String word : words) {
output.collect(new Text(word), new IntVal(1));
}
}
Hadoop
public void map(...) {
…
for (String word : words) {
output.collect(new Text(word), new IntVal(1));
}
}
Wrong
Hadoop
class MyMapper extends Mapper {
Text word = new Text();
IntVal one = new IntVal(1);
public void map(...) {
for (String word : words) {
word.set(word);
output.collect(word, one);
}
}
}
Amazon
AWS ElastiCache
● Strange timeouts (with SO_TIMEOUT 50ms)
● No replication for another cluster
● «Cluster» is not a cluster
● Cluster uses usual instances, so pay for 4
cores while using 1
AWS Limits. You never know where
● Network limit
● PPS rate limit
● LB limit
● Cluster start time up to 20 mins
● Scalability limits
● S3 is slow for many files

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

MongoDB - Sharded Cluster Tutorial
MongoDB - Sharded Cluster TutorialMongoDB - Sharded Cluster Tutorial
MongoDB - Sharded Cluster Tutorial
 
Openstack 簡介
Openstack 簡介Openstack 簡介
Openstack 簡介
 
Declarative Infrastructure Tools
Declarative Infrastructure Tools Declarative Infrastructure Tools
Declarative Infrastructure Tools
 
Prometheus Storage
Prometheus StoragePrometheus Storage
Prometheus Storage
 
Understanding and tuning WiredTiger, the new high performance database engine...
Understanding and tuning WiredTiger, the new high performance database engine...Understanding and tuning WiredTiger, the new high performance database engine...
Understanding and tuning WiredTiger, the new high performance database engine...
 
MongoDB Chunks - Distribution, Splitting, and Merging
MongoDB Chunks - Distribution, Splitting, and MergingMongoDB Chunks - Distribution, Splitting, and Merging
MongoDB Chunks - Distribution, Splitting, and Merging
 
NoSQL Infrastructure - Late 2013
NoSQL Infrastructure - Late 2013NoSQL Infrastructure - Late 2013
NoSQL Infrastructure - Late 2013
 
MongoDB - External Authentication
MongoDB - External AuthenticationMongoDB - External Authentication
MongoDB - External Authentication
 
Linux-Permission
Linux-PermissionLinux-Permission
Linux-Permission
 
MongoDB: Comparing WiredTiger In-Memory Engine to Redis
MongoDB: Comparing WiredTiger In-Memory Engine to RedisMongoDB: Comparing WiredTiger In-Memory Engine to Redis
MongoDB: Comparing WiredTiger In-Memory Engine to Redis
 
RealmDB for Android
RealmDB for AndroidRealmDB for Android
RealmDB for Android
 
MongoDB - Ekino PHP
MongoDB - Ekino PHPMongoDB - Ekino PHP
MongoDB - Ekino PHP
 
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang MeetupДоклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
 
PyCon KR 2019 sprint - RustPython by example
PyCon KR 2019 sprint  - RustPython by examplePyCon KR 2019 sprint  - RustPython by example
PyCon KR 2019 sprint - RustPython by example
 
Nicety of Java 8 Multithreading
Nicety of Java 8 MultithreadingNicety of Java 8 Multithreading
Nicety of Java 8 Multithreading
 
Cassandra
CassandraCassandra
Cassandra
 
Back to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDBBack to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDB
 
Triggers In MongoDB
Triggers In MongoDBTriggers In MongoDB
Triggers In MongoDB
 
Managing Data and Operation Distribution In MongoDB
Managing Data and Operation Distribution In MongoDBManaging Data and Operation Distribution In MongoDB
Managing Data and Operation Distribution In MongoDB
 
Thanos - Prometheus on Scale
Thanos - Prometheus on ScaleThanos - Prometheus on Scale
Thanos - Prometheus on Scale
 

Ähnlich wie Handling 20 billion requests a month

Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
Alexander Dymo
 
Capacity Management from Flickr
Capacity Management from FlickrCapacity Management from Flickr
Capacity Management from Flickr
xlight
 
Infrastructure Monitoring with Postgres
Infrastructure Monitoring with PostgresInfrastructure Monitoring with Postgres
Infrastructure Monitoring with Postgres
Steven Simpson
 

Ähnlich wie Handling 20 billion requests a month (20)

Tweaking perfomance on high-load projects_Думанский Дмитрий
Tweaking perfomance on high-load projects_Думанский ДмитрийTweaking perfomance on high-load projects_Думанский Дмитрий
Tweaking perfomance on high-load projects_Думанский Дмитрий
 
Tweaking performance on high-load projects
Tweaking performance on high-load projectsTweaking performance on high-load projects
Tweaking performance on high-load projects
 
Partner Webinar: MongoDB and Softlayer on Bare Metal: Stability, Performance,...
Partner Webinar: MongoDB and Softlayer on Bare Metal: Stability, Performance,...Partner Webinar: MongoDB and Softlayer on Bare Metal: Stability, Performance,...
Partner Webinar: MongoDB and Softlayer on Bare Metal: Stability, Performance,...
 
Leveraging the Power of Solr with Spark: Presented by Johannes Weigend, QAware
Leveraging the Power of Solr with Spark: Presented by Johannes Weigend, QAwareLeveraging the Power of Solr with Spark: Presented by Johannes Weigend, QAware
Leveraging the Power of Solr with Spark: Presented by Johannes Weigend, QAware
 
Leveraging the Power of Solr with Spark
Leveraging the Power of Solr with SparkLeveraging the Power of Solr with Spark
Leveraging the Power of Solr with Spark
 
How Opera Syncs Tens of Millions of Browsers and Sleeps Well at Night
How Opera Syncs Tens of Millions of Browsers and Sleeps Well at NightHow Opera Syncs Tens of Millions of Browsers and Sleeps Well at Night
How Opera Syncs Tens of Millions of Browsers and Sleeps Well at Night
 
Non-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.js
 
Update on OpenTSDB and AsyncHBase
Update on OpenTSDB and AsyncHBase Update on OpenTSDB and AsyncHBase
Update on OpenTSDB and AsyncHBase
 
R the unsung hero of Big Data
R the unsung hero of Big DataR the unsung hero of Big Data
R the unsung hero of Big Data
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of users
 
Become a Java GC Hero - All Day Devops
Become a Java GC Hero - All Day DevopsBecome a Java GC Hero - All Day Devops
Become a Java GC Hero - All Day Devops
 
MariaDB Paris Workshop 2023 - Performance Optimization
MariaDB Paris Workshop 2023 - Performance OptimizationMariaDB Paris Workshop 2023 - Performance Optimization
MariaDB Paris Workshop 2023 - Performance Optimization
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADta
 
Data Pipeline at Tapad
Data Pipeline at TapadData Pipeline at Tapad
Data Pipeline at Tapad
 
Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
Alexander Dymo - RailsConf 2014 - Improve performance: Optimize Memory and Up...
 
Capacity Management from Flickr
Capacity Management from FlickrCapacity Management from Flickr
Capacity Management from Flickr
 
XPDS14: Efficient Interdomain Transmission of Performance Data - John Else, C...
XPDS14: Efficient Interdomain Transmission of Performance Data - John Else, C...XPDS14: Efficient Interdomain Transmission of Performance Data - John Else, C...
XPDS14: Efficient Interdomain Transmission of Performance Data - John Else, C...
 
OpenTSDB 2.0
OpenTSDB 2.0OpenTSDB 2.0
OpenTSDB 2.0
 
ETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetupETL with SPARK - First Spark London meetup
ETL with SPARK - First Spark London meetup
 
Infrastructure Monitoring with Postgres
Infrastructure Monitoring with PostgresInfrastructure Monitoring with Postgres
Infrastructure Monitoring with Postgres
 

Kürzlich hochgeladen

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Kürzlich hochgeladen (20)

Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
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
 
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
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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)
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
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...
 
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...
 
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
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
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?
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

Handling 20 billion requests a month

  • 2. Dmitriy Dumanskiy Cogniance, mGage project Java Team Lead Java blog : habrahabr.ru/users/doom369/topics
  • 3. Project evolution Ad Project 1 Ad Project 2 XXXX
  • 4. Ad Project 1 delivery load 3 billions req/mon. ~8 c3.xLarge Amazon instances. Average load : 2400 req/sec Peak : x10
  • 5. Ad Project 2 delivery load 14 billions req/mon. ~16 c3.xLarge Amazon instances. Average load : 6000 req/sec Peak : x6
  • 6. XXXX delivery Load 20 billions req/mon. ~14 c3.xLarge Amazon instances. Average load : 11000 req/sec Peak : x6
  • 7. Is it a lot? Average load : 11000 req/sec
  • 8. Twitter : new tweets 15 billions a month Average load : 5700 req/sec Peak : x30
  • 9. Delivery load Requests per month Max load per instance, req/sec Requirements Servers, AWS c3. xLarge Ad Project 1 3 billions 300 HTTP Time 95% < 60ms 8 Ad Project 2 14 billions 400 HTTP Time 95% < 100ms 16 XXXX 20 billions 800 HTTPS Time 99% < 100ms 14
  • 10. Delivery load c3.XLarge - 4 vCPU, 2.8 GHz Intel Xeon E5-2680 LA - ~2-3 1-2 cores reserved for sudden peaks
  • 11. BE tech stacks Ad Project 2: Spring, iBatis, MySql, Solr, Vertica, Cascading, Tomcat Ad Project 1 : Spring, Hibernate, Postgres, Distributed ehCache, Hadoop, Voldemort, Jboss XXXX: Spring, Hibernate, MySQL, Solr, Cascading, Redis, Tomcat
  • 12. Real problem ● ~85 mln active users, ~115 mln registered users ● 11.5 messages per user per day ● ~11000 req/sec ● Peaks 6x ● 99% HTTPS with response time < 100ms ● Reliable and scalable for future grow up to 80k
  • 15. SOLR? Why? ● Pros: ○ Quick search on complex queries ○ Has a lot of build-in features (push- notifications, master-slave replication, RDBMS integration) ● Cons: ○ Only HTTP, embedded performs worth ○ Not easy for beginners ○ Max load is ~100 req/sec per instance
  • 16. “Simple” query "-(-connectionTypes:"+"""+getConnectionType()+"""+" AND connectionTypes:[* TO *]) AND "+"-connectionTypeExcludes:"+"""+getConnectionType()+"""+" AND " + "-(- OSes:"+"(""+osQuery+"" OR ""+getOS()+"")"+" AND OSes:[* TO *]) AND " + "- osExcludes:"+"(""+osQuery+"" OR ""+getOS()+"")" "AND (runOfNetwork:T OR appIncludes:"+getAppId()+" OR pubIncludes:"+getPubId()+" OR categories: ("+categoryList+"))" +" AND -appExcludes:"+getAppId()+" AND -pubExcludes:" +getPubId()+" AND -categoryExcludes:("+categoryList+") AND " + keywordQuery+" AND " + "-(-devices:"+"""+getHandsetNormalized()+"""+" AND devices:[* TO *]) AND " + "-deviceExcludes:"+"""+getHandsetNormalized()+"""+" AND " + "-(-carriers:"+""" +getCarrier()+"""+" AND carriers:[* TO *]) AND " + "-carrierExcludes:"+""" +getCarrier()+"""+" AND " + "-(-locales:"+"(""+locale+"" OR ""+langOnly+"")" +" AND locales:[* TO *]) AND " + "-localeExcludes:"+"(""+locale+"" OR "" +langOnly+"") AND " + "-(-segments:("+segmentQuery+") AND segments:[* TO *]) AND " + "-segmentExcludes:("+segmentQuery+")" + " AND -(-geos:"+geoQuery+" AND geos:[* TO *]) AND " + "-geosExcludes:"+geoQuery
  • 17. Solr Index size < 1 Gb - response time 20-30 ms Index size < 100 Gb - response time 1-2 sec Index size < 400 Gb - response time from 10 secs
  • 18. Architecture MySql Solr Master SOLR Slave AdServer SOLR Slave AdServer SOLR Slave AdServer No-SQL
  • 19. AdServer - Solr Slave Delivery: volatile DeliveryData cache; Cron Job: DeliveryData tempCache = loadData(); cache = tempCache;
  • 20. Why no-sql? ● Realtime data ● Quick response time ● Simple queries by key ● 1-2 queries to no-sql on every request. Average load 10-20k req/sec and >120k req/sec in peaks. ● Cheap solution
  • 21. Why Redis? Pros ● Easy and light-weight ● Low latency and response time. 99% is < 1ms. Average latency is ~0.2ms ● Up to 100k 'get' commands per second on c1.X-Large ● Cool features (atomic increments, sets, hashes) ● Ready AWS service — ElastiCache
  • 22. Why Redis? Cons ● Single-threaded from the box ● Utilize all cores - sharding/clustering ● Scaling/failover not easy ● Limited up to max instance memory (240GB largest AWS) ● Persistence/swapping may delay response ● Cluster solution not production ready ● Data loss possible
  • 23. DynamoDB vs Redis Price per month Put, 95% Get, 95% Rec/sec DynamoDB 58$ 300ms 150ms 50 DynamoDB 580$ 60ms 8ms 780 DynamoDB 5800$ 16ms 8ms 1250 Redis 200$ (c1.medium) 3ms <1ms 4000 ElastiCache 600$ (c1.xlarge) <1ms <1ms 10000
  • 24. What about others? ● Cassandra ● Voldemort ● Memcached
  • 25. Redis RAM problem ● 1 user entry ~ from 80 bytes to 3kb ● ~85 mln users ● Required RAM ~ from 1 GB to 300 GB
  • 26. Data compression Json → Kryo binary → 4x times less data → Gzipping → 2x times less data == 8x less data Now we need < 40 GB + Less load on network stack
  • 27. AdServer BE Average response time — ~1.2 ms Load — 800 req/sec with LA ~4 c3.XLarge == 4 vCPU
  • 28. AdServer BE ● Logging — 12% of time (5% on SSD); ● Response generation — 15% of time; ● Redis request — 50% of time; ● All business logic — 23% of time;
  • 29. Reporting AdServer Hadoop ETL MySQLConsole S3 S3 Delivery logs Aggregated logs 1 hour batch
  • 30. Delivery log structure { "uid":"test", "platform":"android", "app":"xxx", "ts":1375952275223, "pid":1, "education":"Some-Highschool-or-less", "type":"new", "sh":1280, "appver":"6.4.34", "country":"AU", "time":"Sat, 03 August 2013 10:30:39 +0200", "deviceGroup":7, "rid":"fc389d966438478e9554ed15d27713f51", "responseCode":200, "event":"ad", "device":"N95", "sw":768, "ageGroup":"18-24", "preferences":["beer","girls"] }
  • 31. Log structure ● 1 mln. records == 0.6 GB. ● ~900 mln records a day == ~0.55 TB. ● 1 month up to 20 TB of data. ● Zipped data is 10 times less.
  • 32. Reporting Customer : “And we need fancy reporting” But 20 TB of data per month is huge. So what we can do?
  • 33. Reporting Dimensions: device, os, osVer, sreenWidth, screenHeight, country, region, city, carrier, advertisingId, preferences, gender, age, income, sector, company, language, etc... Use case: I want to know how many users saw my ad in San- Francisco.
  • 34. Reporting Geo table: Country, City, Region, CampaignId, Date, counters; Device table: Device, Carrier, Platform, CampaignId, Date, counters; Uniques table: CampaignId, UID
  • 35. Predefined report types → aggregation by predefined dimensions → 500-1000 times less data 20 TB per month → 40 GB per month
  • 36. Of course - hadoop ● Pros: ○ Unlimited (depends) horizontal scaling ● Cons: ○ Not real-time ○ Processing time directly depends on quality code and on infrastructure cost. ○ Not all input can be scaled ○ Cluster startup is so... long
  • 37. Timing ● Hadoop (cascading) : ○ 25 GB in peak hour takes ~40min (-10 min). CSV output 300MB. With cluster of 4 c3.xLarge. ● MySQL: ○ Put 300MB in DB with insert statements ~40 min.
  • 38. Timing ● Hadoop (cascading) : ○ 25 GB in peak hour takes ~40min (-10 min). CSV output 300MB. With cluster of 4 c3.xLarge. ● MySQL: ○ Put 300MB in DB with insert statements ~40 min. ● MySQL: ○ Put 300MB in DB with optimizations ~5 min.
  • 39. Optimized are ● No “insert into”. Only “load data” - ~10 times faster ● “ENGINE=MyISAM“ vs “INNODB” when possible - ~5 times faster ● For “upsert” - temp table with “ENGINE=MEMORY” - IO savings
  • 40. Cascading Hadoop: void map(K key, V val, OutputCollector collector) { ... } void reduce(K key, Iterator<V> vals, OutputCollector collector) { ... } Cascading: Scheme sinkScheme = new TextLine(new Fields( "word", "count")); Pipe assembly = new Pipe("wordcount"); assembly = new Each(assembly, new Fields( "line" ), new RegexGenerator(new Fields("word"), ",") ); assembly = new GroupBy(assembly, new Fields( "word")); Aggregator count = new Count(new Fields( "count")); assembly = new Every(assembly, count);
  • 41. Why cascading? Hadoop Job 1 Hadoop Job 2 Hadoop Job 3 Result of one job should be processed by another job
  • 43. Facts ● HTTP x2 faster HTTPS ● HTTPS keep-alive +80% performance ● Java 7 40% faster Java 6 (our case) ● All IO operations minimized ● Less OOP - better performance
  • 44. Cost of IO L1 cache 3 cycles L2 cache 14 cycles RAM 250 cycles Disk 41 000 000 cycles Network 240 000 000 cycles
  • 45. Cost of IO @Cacheable is everywhere
  • 46. Java 7. Random return items.get(new Random().nextInt(items.size()))
  • 47. Java 7. Random return items.get(ThreadLocalRandom().current().nextInt(items. size())) ~3x
  • 48. Java 7. Less garbage new ArrayList(): this.elementData = {}; insteadOf this.elementData = new Object [10]; new HashMap(): Entry<K,V>[] table = {}; insteadOf this.table = new Entry[16];
  • 49. Java 7. Less garbage Before: class String { int offset; int count; char value[]; int hash; } After: class String { char value[]; int hash; }
  • 50. Java 7. GC 200mb per second - 0.5% CPU time Smaller heap - better performance
  • 51. Java 7. String ● Substring ● Split
  • 52. Use latest versions Jedis 2.2.3 uses commons-pool 1.6 Jedis 2.3 uses commons-pool 2.0 commons-pool 2.0 - ~2x times faster
  • 53. Small tweaks. Date new Date() vs System.currentTimeMillis()
  • 54. Small tweaks. SimpleDateFormat return new SimpleDateFormat(“MMM yyyy HH:mm:ss Z”).parse (dateString)
  • 55. Small tweaks. SimpleDateFormat ● ThreadLocal ● Joda - threadsafe DateTimeFormat
  • 56. Small tweaks. Pattern public Item isValid(String ip) { Pattern pattern = Pattern.compile("xxx"); Matcher matcher = pattern.matcher(ip); return matcher.matches(); }
  • 57. Small tweaks. Pattern final Pattern pattern = Pattern.compile("xxx"); final Matcher matcher = pattern.matcher(“”); public Item isValid(String ip) { matcher.reset(ip); return matcher.matches(); }
  • 59. Small tweaks. String.split item.getPreferences().split(“[_,;,-]”); vs static final Pattern PATTERN = Pattern.compile("[_,;,-]"); PATTERN.split(item.getPreferences()) - ~2x faster vs custom code - up to 5x faster
  • 60. Small tweaks. FOR loop for (A a : arrayListA) { // do something for (B b : arrayListB) { // do something for (C c : arrayListC) { // do something } } }
  • 61. Small tweaks. FOR loop for (Iterator<A> i = arrayListA.iterator(); i.hasNext();) { a = i.next(); } public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor = 0; int lastRet = -1; int expectedModCount = modCount; }
  • 64. Small tweaks. Primitives double coord = Double.valueOf(textLine);
  • 66. Avoid concurrency JedisPool.getResource() - sync JedisPool.returnResource() - sync OutputStreamWriter.write() - sync UUID.randomUUID() - sync
  • 68. Avoid concurrency ThreadLocal<JedisConnection> - requires ~1000 open connections for Redis. More connections — slower redis response. Dead end.
  • 69. Avoid concurrency OutputStreamWriter.write() ● No flush() on every request and big buffered writer ● Async writer No guarantee for no data loss. Dead end.
  • 71. Hadoop Map input : 300 MB Map output : 80 GB
  • 72. Hadoop ● mapreduce.map.output.compress = true ● codecs: GZip, BZ2 - CPU intensive ● codecs: LZO, Snappy ● codecs: JNI ~x10
  • 74. Hadoop Text, IntWritable, BytesWritable, NullWritable, etc Simpler - better
  • 75. Hadoop map(T value, ...) { Log log = parse(value); Data data = dbWrapper.getSomeMissingData(log.getCampId()); }
  • 76. Hadoop Missing data: map(T value, ...) { Log log = parse(value); Data data = dbWrapper.getSomeMissingData(log.getCampId()); } Wrong
  • 77. Hadoop map(T value, ...) { Log log = parse(value); Key resultKey = makeKey(log.getCampName(), ...); output.collect(resultKey, resultValue); }
  • 78. Hadoop Unnecessary data: map(T value, ...) { Log log = parse(value); Key resultKey = makeKey(log.getCampName(), ...); output.collect(resultKey, resultValue); } Wrong
  • 79. Hadoop RecordWriter.write(K key, V value) { Entity entity = makeEntity(key, value); dbWrapper.save(entity); }
  • 80. Hadoop Minimize IO: RecordWriter.write(K key, V value) { Entity entity = makeEntity(key, value); dbWrapper.save(entity); } Wrong
  • 81. Hadoop public boolean equals(Object obj) { EqualsBuilder equalsBuilder = new EqualsBuilder(); equalsBuilder.append(id, otherKey.getId()); ... } public int hashCode() { HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(); hashCodeBuilder.append(id); ... }
  • 82. Hadoop public boolean equals(Object obj) { EqualsBuilder equalsBuilder = new EqualsBuilder(); equalsBuilder.append(id, otherKey.getId()); ... } public int hashCode() { HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(); hashCodeBuilder.append(id); ... } Wrong
  • 83. Hadoop public void map(...) { … for (String word : words) { output.collect(new Text(word), new IntVal(1)); } }
  • 84. Hadoop public void map(...) { … for (String word : words) { output.collect(new Text(word), new IntVal(1)); } } Wrong
  • 85. Hadoop class MyMapper extends Mapper { Text word = new Text(); IntVal one = new IntVal(1); public void map(...) { for (String word : words) { word.set(word); output.collect(word, one); } } }
  • 87. AWS ElastiCache ● Strange timeouts (with SO_TIMEOUT 50ms) ● No replication for another cluster ● «Cluster» is not a cluster ● Cluster uses usual instances, so pay for 4 cores while using 1
  • 88. AWS Limits. You never know where ● Network limit ● PPS rate limit ● LB limit ● Cluster start time up to 20 mins ● Scalability limits ● S3 is slow for many files