SlideShare a Scribd company logo
1 of 84
Download to read offline
How to survive in a BASE world
A practical guide for the dauntless developer
Uwe Friedrichsen, codecentric AG, 2013
Uwe Friedrichsen
@ufried
ACID vs. BASE
A C I DAtomicity Consistency Isolation Durability
B A S EBasically Available Soft State Eventually
Consistent
ACID
• Strong consistency
• Isolation
• Focus on “commit”
• Nested transactions
• Availability?
• Conservative (pessimistic)
• Difficult evolution (e.g.
schema)
BASE
• Weak consistency (stale data OK)
• Availability first
• Best effort
• Approximate answers OK
• Aggressive (optimistic)
• Simpler!
• Faster
• Easier evolution
But I think it’s a spectrum
ACID vs. BASE
Source: Eric Brewer, Towards Robust Distributed Systems, PODC Keynote, July-19-2000
Consequences
• No ACID properties across entities
• No ACID properties across nodes
• ACID properties for single entity on single node
A (very) simple example
customer
id : long
name : string
book
id : long
title : string
author : string
loaned by loaned
0..1 0..n
loan(customer, book) : void
return(customer, book) : void
booksLoaned(customer) : list of book
isBookLoaned(book) : boolean
Data model
Actions
Iteration #0
RDBMS – ACID – JPA
JPA Entity Class Customer
@Entity
public class Customer {
@Id
@GeneratedValue
private long id;
private String name;
@OneToMany(mappedBy = "customer")
private final List<Book> loanedBooks;
<Methods>
}
JPA Entity Class Book
@Entity
public class Book {
@Id
@GeneratedValue
private long id;
private String title;
private String author;
private Customer customer;
<Methods>
}
Database model
Foreign Key to
CUSTOMER.ID
TABLE CUSTOMER
ID
NAME
TABLE BOOK
ID
TITLE
AUTHOR
CUSTOMER (FK)
Action „loan“ using JPA
public void loan(long customerId, long bookId) {
<Get EntityManager>
em.getTransaction().begin();
<Read customer and book from database>
customer.getLoanedBooks().add(book);
book.setCustomer(customer);
em.persist(customer);
em.persist(book);
em.getTransaction().commit();
<Cleanup>
}
Same for action „return“
Action „isBookLoaned“ using JPA
public boolean isBookLoaned(long bookId) {
<Get EntityManager>
Query q = em.createQuery("SELECT b FROM Book b WHERE b.id = :id");
q.setParameter("id", bookId);
Book book = (Book) q.getSingleResult();
return book.getCustomer() != null;
}
Action „booksLoaned“ using JPA
public List<Book> booksLoaned(long customerId) {
<Get EntityManager>
Query q =
em.createQuery("SELECT c FROM Customer c WHERE c.id = :id");
q.setParameter("id", customerId);
Customer customer = (Customer) q.getSingleResult();
return customer.getLoanedBooks();
}
Boils down to an implicitly executed SQL query that looks like
SELECT … FROM BOOK WHERE CUSTOMERID = <customerId>
Mutating action
• begin transaction
• do required changes
• commit
Non-mutating action
• create query
• execute query
• navigate in result set
(implicitly executing additional queries if required)
Wrapup ACID model
Iteration #1
NoSQL – BASE – naïve
Mutating action
• begin transaction
• do required changes
• commit
Non-mutating action
• create query
• execute query
• navigate in result set
(implicitly executing additional queries if required)
NaĂŻve BASE model
???
Data model
Customer
TABLE CUSTOMER
ID
NAME
Book
TABLE BOOK
ID
TITLE
AUTHOR
CUSTOMER (FK)
{
"id" : <id>,
"name" : "<name>"
}
{
"id" : <id>,
"title" : "<title>",
"author" : "<author>",
"customerId" : <id>
}
JPA Entity Class Customer
@Entity
public class Customer {
@Id
@GeneratedValue
private long id;
private String name;
@OneToMany(mappedBy = "customer")
private final List<Book> loanedBooks;
<Methods>
}
Need to take care of ID generation ourselves
Gone for the moment (naĂŻve approach)
Class Customer
public class Customer {
private long id;
private String name;
<Methods>
}
JPA Entity Class Book
@Entity
public class Book {
@Id
@GeneratedValue
private long id;
private String title;
private String author;
private Customer customer;
<Methods>
}
Need to take care of ID generation ourselves
Gone for the moment (naĂŻve approach)
Class Book
public class Book {
private long id;
private String title;
private String author;
private long customerId;
<Methods>
}
Only the ID
Action „loan“, „return“ & „isBookLoaned“
public void loan(long customerId, long bookId) {
Book book = readBook(bookId);
book.setCustomerId(customerId);
writeBook(book);
}
public void return(long customerId, long bookId) {
Book book = readBook(bookId);
book.setCustomerId(0L);
writeBook(book);
}
public boolean isBookLoaned(long bookId) {
Book book = readBook(bookId);
return book.getCustomerId() > 0L;
}
readBook
private Book readBook(long id) {
String json = readBookFromDb(id);
return toBook(json);
}
private Book toBook(String json) {
JSONObject jo = new JSONObject(json);
Book b = new Book(jo.getLong("id"), jo.getString("title"),
jo.getString("author"), jo.getLong("customerId"));
return b;
}
Same for „readCustomer“ and „toCustomer“
writeBook
private void writeBook(Book b) {
long key = b.getId();
String json = fromBook(b);
writeBookToDb(key, json);
}
private String fromBook(Book b) {
JSONObject jo = new JSONObject();
jo.put("id", b.getId());
jo.put("title", c.getTitle());
jo.put("author", c.getAuthor());
jo.put("customerId", b.getCustomerId());
return jo.toString();
}
Same for „writeCustomer“ and „fromCustomer“
Action „booksLoaned“
public List<Book> booksLoaned(long customerId) {
List<Book> loanedBooks = new ArrayList<Book>();
Iterator<Book> it = readAllBooks();
for (Book b : it) {
if (book.getCustomerId() == customerId) {
loanedBooks.add(b);
}
}
return loanedBooks;
}
private Iterator<Book> readAllBooks() {
DBIterator dbi = readAllBooksFromDb(); // Iterator<String> (json)
return new BookIterator(dbi);
}
BookIterator
public class BookIterator implements Iterator<Book> {
private final DBIterator dbi;
public BookIterator(DBIterator dbi) {
this.dbi = dbi;
}
@Override public boolean hasNext() {
return dbi.hasNext();
}
@Override public Book next() {
return toBook(dbi.next());
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
}
Iteration #2
Handling inconsistencies
across replica sets
Assume the following code sequence
loan(2312L, 4711L);
boolean isLoaned = isBookLoaned(4711L);
Question: Which value has isLoaned?
Quick exercise
Alternative #1
Replica
Node 1
Replica
Node 3
Client
replicate
2
loan1 isLoaned 3
Replica
Node 2

Alternative #2
Replica
Node 1
Replica
Node 3
Client
replicate
3
loan1 isLoaned 2
Replica
Node 2

Read your own writes
Solution #1
Read your
own writes
Replica
Node 1
Replica
Node 3
Client
replicate
?
loan1 isLoaned 2
Replica
Node 2
Read from master
Solution #2
Read from
master
Master Slave 2
Client
replicate
?
loan1 isLoaned 2
Slave 1
Quorum
• W > N/2
• R + W > N
Solution #3
readBook & writeBook
private Book readBook(long id) {
String json = readBookFromDb(id, READ_QUORUM);
return toBook(json);
}
private void writeBook(Book b) {
long key = b.getId();
String json = fromBook(b);
writeBookToDb(key, json, WRITE_QUORUM);
}
Same for „readCustomer“ and „writeCustomer“
Iteration #3
Handling siblings
due to partitioning
Assume the following code sequence
boolean isLoaned = isBookLoaned(4711L);
Question: What do you get?
Quick exercise
isBookLoaned(4711L)
public boolean isBookLoaned(4711L) {
Book book = readBook(4711L);
return book.getCustomerId() > 0L;
}
private Book readBook(4711L) {
String json = readBookFromDb(4711L);
return toBook(json);
}
private Book toBook(String json) {
JSONObject jo = new JSONObject(json);
Book b = new Book(jo.getLong("id"), jo.getString("title"),
jo.getString("author"), jo.getLong("customerId"));
return b;
}
Expects a “normal” book JSON
… but your JSON looks like this
{ "siblings" : [
{
"id" : 4711L,
"title" : "The Catcher in the Rye",
"author" : "J. D. Salinger",
"customerId" : 2312L
},
{
"id" : 4711L,
"title" : "The Catcher in the Rye",
"author" : "J. D. Salinger",
"customerId" : 0L
}
]
}
Leave the decision to the caller
Solution #1
Build a resolver
Solution #2
Extended JSON data model
Customer:
{
"id" : <id>,
"name" : "<name>",
"timestamp" : <timestamp>
}
Book:
{
"id" : <id>,
"title" : "<title>",
"author" : "<author>",
"customerId" : <id>,
"timestamp" : <timestamp>
}
Domain Classes
public class Customer {
private Long id;
private String name;
<Methods>
}
public class Book {
private long id;
private String title;
private String author;
private long customerId;
<Methods>
}
Timestamp not required
in the domain classes
fromBook
private String fromBook(Book b) {
JSONObject jo = new JSONObject();
jo.put("id", b.getId());
jo.put("title", c.getTitle());
jo.put("author", c.getAuthor());
jo.put("customerId", b.getCustomerId());
jo.put("timestamp", System.currentTimeMillis());
return jo.toString();
}
Same for „fromCustomer“
Timestamp added
in mapping
toBook
private Book toBook(String json) {
JSONObject jo = new JSONObject(resolveBook(json));
Book b = new Book(jo.getLong("id"), jo.getString("title"),
jo.getString("author"), jo.getLong("customerId"));
return b;
}
Same for „toCustomer“
resolveBook
private String resolveBook(String json) {
JSONObject jo = new JSONObject(json);
JSONArray siblings = jo.optJSONArray("siblings");
if (siblings == null) {
return json;
}
int index = 0;
long timestamp = 0L
for (int i = 0; i < siblings.length(); i++) {
long t = siblings.getJSONObject(i).getLong("timestamp");
if (t > timestamp) {
index = i;
timestamp = t;
}
}
return siblings.getJSONObject(index).toString();
}
Conflict-free replicated data types
Solution #3
Iteration #4
Read optimizations
Assume the following method to retrieve the
number of books a customer has loaned
public int numberOfBooksLoaned(long cId) {
return booksLoaned(cId).size();
}
Question: How is the performance?
Quick exercise
Remember the implementation
public List<Book> booksLoaned(long customerId) {
List<Book> loanedBooks = new ArrayList<Book>();
Iterator<Book> it = readAllBooks();
for (Book b : it) {
if (book.getCustomerId() == customerId) {
loanedBooks.add(b);
}
}
return loanedBooks;
}
private Iterator<Book> readAllBooks() {
DBIterator dbi = readAllBooksFromDb(); // Iterator<String> (json)
return new BookIterator(dbi);
}
Reads all book entities distributed across all nodes
Use secondary indices
Solution #1
Re-implementation using indices
public List<Book> booksLoaned(long customerId) {
List<Book> loanedBooks = new ArrayList<Book>();
Iterator<Book> it = readAllBooksLoanedByACustomer(customerId);
for (Book b : it) {
loanedBooks.add(b);
}
return loanedBooks;
}
private Iterator<Book> readAllBooksLoanedByACustomer(long customerId) {
DBIterator dbi =
readAllBooksUsingSecondaryIndexFromDb(long customerId);
return new BookIterator(dbi);
}
• Only works on ACID nodes
• Duplicates while rebalancing
• Partial answers if node is down
Tradeoffs of indices
… but actually you are interested in a property
that logically belongs to a single customer
Denormalize
Solution #2
Denormalized Customer entity
{
"id" : <id>,
"name" : "<name>",
"loanedBooks" : [
{
"id" : <id>,
"title" : "<title>",
"author" : "<author>"
},
...
],
"timestamp" : <timestamp>
}
Can be empty
Denormalized Book entity
{
"id" : <id>,
"title" : "<title>",
"author" : "<author>",
"loanedBy" :
{
"id" : <id>,
"name" : "<name>"
},
"timestamp" : <timestamp>
}
Optional value
Denormalized Customer domain class
public class Customer {
private Long id;
private String name;
private List<BookRef> loanedBooks;
<Methods>
}
public class BookRef { object
private Long id;
private String title;
private String author;
<Methods>
}
Here we go again
Denormalized Book domain class
public class Book {
private Long id;
private String title;
private String author;
private CustomerRef customer;
<Methods>
}
public class CustomerRef {
private Long id;
private String name;
<Methods>
}
Here we go again
Actions „loan“ & „return“
public void loan(long customerId, long bookId) {
Customer customer = readCustomer(customerId);
Book book = readBook(bookId);
customer.getLoanedBooks().add(new BookRef(book));
book.setCustomer(new CustomerRef(customer));
writeCustomer(customer);
writeBook(book);
}
public void return(long customerId, long bookId) {
Customer customer = readCustomer(customerId);
Book book = readBook(bookId);
customer.getLoanedBooks().remove(new BookRef(book));
book.setCustomer(null);
writeCustomer(customer);
writeBook(book);
}
Also mutates
the customer
Actions „booksLoaned“ & „isBookLoaned“
public List<BookRef> booksLoaned(long customerId) {
Customer customer = readCustomer(customerId);
return customer.getLoanedBooks();
}
public boolean isBookLoaned(long bookId) {
Book book = readBook(bookId);
return book.getCustomer() != null;
}
Only one read
required
Check becomes
more expressive
Method “readAllBooks” not required anymore in this scenario
fromCustomer
private String fromCustomer(Customer c) {
JSONObject jo = new JSONObject();
jo.put("id", c.getId());
jo.put("name", c.getName());
JSONArray ja = new JSONArray();
for (BookRef b : c.getLoanedBooks()) {
JSONObject jb = new JSONObject();
jb.put("id", b.getId());
jb.put("title", c.getTitle());
jb.put("author", c.getAuthor());
ja.put(jb);
}
jo.put("loanedBooks", ja);
jo.put("timestamp", System.currentTimeMillis());
return jo.toString();
}
Also map
book references
toCustomer
private Customer toCustomer(String json) {
JSONObject jo = new JSONObject(json);
JSONArray ja = jo.getJSONArray("loanedBooks");
List<BookRef> loanedBooks = new ArrayList<BookRef>();
for (int i = 0; i < ja.length(); i++) {
JSONObject jb = ja.getJSONObject(i);
BookRef b = new BookRef(jb.getLong("id"),
jb.getString("title"),
jb.getString("author"));
loanedBooks.add(b);
}
Customer c = new Customer(jo.getLong("id"), jo.getString("name"),
loanedBooks);
return c;
}
Also map
book references
fromBook
private String fromBook(Book b) {
JSONObject jo = new JSONObject();
jo.put("id", b.getId());
jo.put("title", c.getTitle());
jo.put("author", c.getAuthor());
if (c.getCustomer() != null) {
JSONObject jc = new JSONObject();
jc.put("id", c.getCustomer().getId());
jc.put("name", c.getCustomer().getName());
jo.put("loanedBy", jc);
}
jo.put("timestamp", System.currentTimeMillis());
return jo.toString();
}
Also map
customer
reference
toBook
private Book toBook(String json) {
JSONObject jo = new JSONObject(json);
CustomerRef c = null;
JSONObject jc = jo.optJSONObject("loanedBy");
if (jc != null) {
c = new CustomerRef(jc.getLong("id"), jc.getString("name"));
}
Book b = new Book(jo.getLong("id"), jo.getString("title"),
jo.getString("author"), c);
return b;
}
Also map
customer
reference
• All data within one entity
• Coarse grained entities
• Often huge read speedups
• No OR-Mapper equivalent
• Can result in inconsistencies across entities
Wrapup denormalization
Iteration #5
Handling inconsistencies
across entities
Assume the following code sequence
loan(2312L, 4711L);
long bookId = readCustomer(2312L)
.getLoanedBooks().get(0).getId();
long customerId = readBook(4711L)
.getCustomer().getId();
Question: What do you get?
Quick exercise
Remember the implementation
public void loan(2312L, 4711L) {
Customer customer = readCustomer(2312L);
Book book = readBook(4711L);
customer.getLoanedBooks().add(new BookRef(book));
book.setCustomer(new CustomerRef(customer));
writeCustomer(customer);
writeBook(book);
}
This call fails
Leads to the following entity state
{
"id" : 2312L,
"name" : "Uwe Friedrichsen",
"loanedBooks" : [
{
"id" : 4711L,
"title" : "The Catcher in the Rye",
"author" : "J. D. Salinger"
}
],
"timestamp" : <timestamp>
}
{
"id" : 4711L,
"title" : "The Catcher in the Rye",
"author" : "J. D. Salinger",
"timestamp" : <timestamp>
}
On-the-fly resolver
Solution #1
Actions „loan“ & „return“
public void loan(long customerId, long bookId) {
Customer customer = readCustomer(customerId);
Book book = readBook(bookId);
customer.getLoanedBooks().add(new BookRef(book));
book.setCustomer(new CustomerRef(customer));
writeBook(book);
writeCustomer(customer);
}
public void return(long customerId, long bookId) {
Customer customer = readCustomer(customerId);
Book book = readBook(bookId);
customer.getLoanedBooks().remove(new BookRef(book));
book.setCustomer(null);
writeBook(book);
writeCustomer(customer);
}
Switched
write order
resolveIfRequired
private void resolveIfRequired(Customer c, Book b) {
BookRef br = new BookRef(b.getId(), b.getTitle(), b.getAuthor());
if (!c.getLoanedBooks().contains(br)) {
c.getLoanedBooks.add(br);
}
}
// some code that (for some reason) reads both related entities
...
Book book = readBook(bookId);
Customer customer = null;
If (book.getCustomer() != null) {
readCustomer(book.getCustomer().getId());
resolveIfRequired(customer, book);
}
// Do stuff with customer and book
...
On-the-fly resolver with write-back (“read repair”)
Solution #2
resolveIfRequired
private void resolveIfRequired(Customer c, Book b) {
BookRef br = new BookRef(b.getId(), b.getTitle(), b.getAuthor());
if (!c.getLoanedBooks().contains(br)) {
c.getLoanedBooks.add(br);
writeCustomer(c);
}
}
Best effort principle
Consistency crawler
Compensating actions
Change journal
…
Advanced solutions
???
Wrap-up
• BASE is different
• New challenges for a developer
• Some databases promise to hide BASE …
… but you can‘t fool the laws of distribution
• Inconsistencies will happen – be prepared
The real world is also BASE
Welcome to reality … ;-)
Uwe Friedrichsen
@ufried
uwe.friedrichsen@codecentric.de
http://www.slideshare.net/ufried/
http://blog.codecentric.de/author/ufr
How to survive in a BASE world

More Related Content

What's hot

MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: Tutorial
MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: TutorialMongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: Tutorial
MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: TutorialMongoDB
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)shubhamvcs
 
Java script Advance
Java script   AdvanceJava script   Advance
Java script AdvanceJaya Kumari
 
Creating a Single View: Data Design and Loading Strategies
Creating a Single View: Data Design and Loading StrategiesCreating a Single View: Data Design and Loading Strategies
Creating a Single View: Data Design and Loading StrategiesMongoDB
 
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...MongoDB
 
1 24 - user data management
1 24 - user data management1 24 - user data management
1 24 - user data managementMongoDB
 
Ch09 -Managing State and Information Security
Ch09 -Managing State and Information SecurityCh09 -Managing State and Information Security
Ch09 -Managing State and Information Securitydcomfort6819
 
Mongo db tutorials
Mongo db tutorialsMongo db tutorials
Mongo db tutorialsAnuj Jain
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDBMongoDB
 
Webinar: User Data Management with MongoDB
Webinar: User Data Management with MongoDBWebinar: User Data Management with MongoDB
Webinar: User Data Management with MongoDBMongoDB
 
6.5 Query (কোয়েরি)
6.5 Query (কোয়েরি)6.5 Query (কোয়েরি)
6.5 Query (কোয়েরি)Mohammad Ali Khan
 
NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020Thodoris Bais
 
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...MongoDB
 
MongoDB Schema Design
MongoDB Schema DesignMongoDB Schema Design
MongoDB Schema DesignAlex Litvinok
 
S01 e01 schema-design
S01 e01 schema-designS01 e01 schema-design
S01 e01 schema-designMongoDB
 
Android and firebase database
Android and firebase databaseAndroid and firebase database
Android and firebase databaseNILESH SAWARDEKAR
 
Indexing Strategies to Help You Scale
Indexing Strategies to Help You ScaleIndexing Strategies to Help You Scale
Indexing Strategies to Help You ScaleMongoDB
 

What's hot (19)

MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: Tutorial
MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: TutorialMongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: Tutorial
MongoDB .local Chicago 2019: Practical Data Modeling for MongoDB: Tutorial
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)
 
Java script Advance
Java script   AdvanceJava script   Advance
Java script Advance
 
Creating a Single View: Data Design and Loading Strategies
Creating a Single View: Data Design and Loading StrategiesCreating a Single View: Data Design and Loading Strategies
Creating a Single View: Data Design and Loading Strategies
 
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...
Creating a Single View Part 2: Loading Disparate Source Data and Creating a S...
 
1 24 - user data management
1 24 - user data management1 24 - user data management
1 24 - user data management
 
Storekit diagram
Storekit diagramStorekit diagram
Storekit diagram
 
Ch09 -Managing State and Information Security
Ch09 -Managing State and Information SecurityCh09 -Managing State and Information Security
Ch09 -Managing State and Information Security
 
AngularJS
AngularJSAngularJS
AngularJS
 
Mongo db tutorials
Mongo db tutorialsMongo db tutorials
Mongo db tutorials
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDB
 
Webinar: User Data Management with MongoDB
Webinar: User Data Management with MongoDBWebinar: User Data Management with MongoDB
Webinar: User Data Management with MongoDB
 
6.5 Query (কোয়েরি)
6.5 Query (কোয়েরি)6.5 Query (কোয়েরি)
6.5 Query (কোয়েরি)
 
NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020
 
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...
MongoDB .local Munich 2019: Still Haven't Found What You Are Looking For? Use...
 
MongoDB Schema Design
MongoDB Schema DesignMongoDB Schema Design
MongoDB Schema Design
 
S01 e01 schema-design
S01 e01 schema-designS01 e01 schema-design
S01 e01 schema-design
 
Android and firebase database
Android and firebase databaseAndroid and firebase database
Android and firebase database
 
Indexing Strategies to Help You Scale
Indexing Strategies to Help You ScaleIndexing Strategies to Help You Scale
Indexing Strategies to Help You Scale
 

Viewers also liked

Fault tolerance made easy
Fault tolerance made easyFault tolerance made easy
Fault tolerance made easyUwe Friedrichsen
 
Dr. Hectic and Mr. Hype - surviving the economic darwinism
Dr. Hectic and Mr. Hype - surviving the economic darwinismDr. Hectic and Mr. Hype - surviving the economic darwinism
Dr. Hectic and Mr. Hype - surviving the economic darwinismUwe Friedrichsen
 
Devops for Developers
Devops for DevelopersDevops for Developers
Devops for DevelopersUwe Friedrichsen
 
Resilience with Hystrix
Resilience with HystrixResilience with Hystrix
Resilience with HystrixUwe Friedrichsen
 
Patterns of resilience
Patterns of resiliencePatterns of resilience
Patterns of resilienceUwe Friedrichsen
 
The promises and perils of microservices
The promises and perils of microservicesThe promises and perils of microservices
The promises and perils of microservicesUwe Friedrichsen
 
Resilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsResilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsUwe Friedrichsen
 
Scalability patterns
Scalability patternsScalability patterns
Scalability patternsUwe Friedrichsen
 
Komplexität - Na und?
Komplexität - Na und?Komplexität - Na und?
Komplexität - Na und?Uwe Friedrichsen
 
Cloud fuer entscheider
Cloud fuer entscheiderCloud fuer entscheider
Cloud fuer entscheiderUwe Friedrichsen
 
Cloud Compliance - Bestimmungen, Zertifizierungen und all das
Cloud Compliance - Bestimmungen, Zertifizierungen und all dasCloud Compliance - Bestimmungen, Zertifizierungen und all das
Cloud Compliance - Bestimmungen, Zertifizierungen und all dasUwe Friedrichsen
 
Emergent architecture
Emergent architectureEmergent architecture
Emergent architectureUwe Friedrichsen
 
Der Business Case fĂźr Architektur
Der Business Case fĂźr ArchitekturDer Business Case fĂźr Architektur
Der Business Case fĂźr ArchitekturUwe Friedrichsen
 
Down with the_sandals
Down with the_sandalsDown with the_sandals
Down with the_sandalsUwe Friedrichsen
 
The agile Architect - Craftsmanship on a new Level
The agile Architect - Craftsmanship on a new LevelThe agile Architect - Craftsmanship on a new Level
The agile Architect - Craftsmanship on a new LevelUwe Friedrichsen
 
No crash allowed - Fault tolerance patterns
No crash allowed - Fault tolerance patternsNo crash allowed - Fault tolerance patterns
No crash allowed - Fault tolerance patternsUwe Friedrichsen
 
Hochskalierbare Cloud-Architekturen
Hochskalierbare Cloud-ArchitekturenHochskalierbare Cloud-Architekturen
Hochskalierbare Cloud-ArchitekturenUwe Friedrichsen
 
Kommunikation und Qualität - Java Forum Nord 2016
Kommunikation und Qualität - Java Forum Nord 2016Kommunikation und Qualität - Java Forum Nord 2016
Kommunikation und Qualität - Java Forum Nord 2016Sabine Wojcieszak
 

Viewers also liked (20)

Fault tolerance made easy
Fault tolerance made easyFault tolerance made easy
Fault tolerance made easy
 
Dr. Hectic and Mr. Hype - surviving the economic darwinism
Dr. Hectic and Mr. Hype - surviving the economic darwinismDr. Hectic and Mr. Hype - surviving the economic darwinism
Dr. Hectic and Mr. Hype - surviving the economic darwinism
 
Self healing data
Self healing dataSelf healing data
Self healing data
 
Devops for Developers
Devops for DevelopersDevops for Developers
Devops for Developers
 
Resilience with Hystrix
Resilience with HystrixResilience with Hystrix
Resilience with Hystrix
 
Patterns of resilience
Patterns of resiliencePatterns of resilience
Patterns of resilience
 
The promises and perils of microservices
The promises and perils of microservicesThe promises and perils of microservices
The promises and perils of microservices
 
Resilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsResilience reloaded - more resilience patterns
Resilience reloaded - more resilience patterns
 
Scalability patterns
Scalability patternsScalability patterns
Scalability patterns
 
Komplexität - Na und?
Komplexität - Na und?Komplexität - Na und?
Komplexität - Na und?
 
Cloud fuer entscheider
Cloud fuer entscheiderCloud fuer entscheider
Cloud fuer entscheider
 
Cloud Compliance - Bestimmungen, Zertifizierungen und all das
Cloud Compliance - Bestimmungen, Zertifizierungen und all dasCloud Compliance - Bestimmungen, Zertifizierungen und all das
Cloud Compliance - Bestimmungen, Zertifizierungen und all das
 
Emergent architecture
Emergent architectureEmergent architecture
Emergent architecture
 
Der Business Case fĂźr Architektur
Der Business Case fĂźr ArchitekturDer Business Case fĂźr Architektur
Der Business Case fĂźr Architektur
 
Down with the_sandals
Down with the_sandalsDown with the_sandals
Down with the_sandals
 
The agile Architect - Craftsmanship on a new Level
The agile Architect - Craftsmanship on a new LevelThe agile Architect - Craftsmanship on a new Level
The agile Architect - Craftsmanship on a new Level
 
No crash allowed - Fault tolerance patterns
No crash allowed - Fault tolerance patternsNo crash allowed - Fault tolerance patterns
No crash allowed - Fault tolerance patterns
 
Hochskalierbare Cloud-Architekturen
Hochskalierbare Cloud-ArchitekturenHochskalierbare Cloud-Architekturen
Hochskalierbare Cloud-Architekturen
 
Kommunikation und Qualität - Java Forum Nord 2016
Kommunikation und Qualität - Java Forum Nord 2016Kommunikation und Qualität - Java Forum Nord 2016
Kommunikation und Qualität - Java Forum Nord 2016
 
OAuth 2.0
OAuth 2.0OAuth 2.0
OAuth 2.0
 

Similar to How to survive in a BASE world

buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdf
buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdfbuildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdf
buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdflallababa
 
Webinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsWebinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsMongoDB
 
Webinar: Schema Design
Webinar: Schema DesignWebinar: Schema Design
Webinar: Schema DesignMongoDB
 
Schema Design with MongoDB
Schema Design with MongoDBSchema Design with MongoDB
Schema Design with MongoDBrogerbodamer
 
Webinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsWebinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsMongoDB
 
Back to Basics Webinar 3 - Thinking in Documents
Back to Basics Webinar 3 - Thinking in DocumentsBack to Basics Webinar 3 - Thinking in Documents
Back to Basics Webinar 3 - Thinking in DocumentsJoe Drumgoole
 
Managing Social Content with MongoDB
Managing Social Content with MongoDBManaging Social Content with MongoDB
Managing Social Content with MongoDBMongoDB
 
Back to Basics Webinar 3: Schema Design Thinking in Documents
 Back to Basics Webinar 3: Schema Design Thinking in Documents Back to Basics Webinar 3: Schema Design Thinking in Documents
Back to Basics Webinar 3: Schema Design Thinking in DocumentsMongoDB
 
Modeling JSON data for NoSQL document databases
Modeling JSON data for NoSQL document databasesModeling JSON data for NoSQL document databases
Modeling JSON data for NoSQL document databasesRyan CrawCour
 
Schema Design
Schema DesignSchema Design
Schema DesignMongoDB
 
Schema design
Schema designSchema design
Schema designMongoDB
 
Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopSteven Francia
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersChristopher Batey
 
Schema Design
Schema DesignSchema Design
Schema DesignMongoDB
 
Mongo db 101 dc group
Mongo db 101 dc groupMongo db 101 dc group
Mongo db 101 dc groupJohn Ragan
 
Schema Design
Schema DesignSchema Design
Schema DesignMongoDB
 
10gen Presents Schema Design and Data Modeling
10gen Presents Schema Design and Data Modeling10gen Presents Schema Design and Data Modeling
10gen Presents Schema Design and Data ModelingDATAVERSITY
 
Aggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichAggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichNorberto Leite
 
Freeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureFreeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureDavid Hoerster
 
Schema Design
Schema DesignSchema Design
Schema DesignMongoDB
 

Similar to How to survive in a BASE world (20)

buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdf
buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdfbuildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdf
buildyourfirstmongodbappberlin2013thomas-130313104259-phpapp02.pdf
 
Webinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsWebinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in Documents
 
Webinar: Schema Design
Webinar: Schema DesignWebinar: Schema Design
Webinar: Schema Design
 
Schema Design with MongoDB
Schema Design with MongoDBSchema Design with MongoDB
Schema Design with MongoDB
 
Webinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev TeamsWebinar: General Technical Overview of MongoDB for Dev Teams
Webinar: General Technical Overview of MongoDB for Dev Teams
 
Back to Basics Webinar 3 - Thinking in Documents
Back to Basics Webinar 3 - Thinking in DocumentsBack to Basics Webinar 3 - Thinking in Documents
Back to Basics Webinar 3 - Thinking in Documents
 
Managing Social Content with MongoDB
Managing Social Content with MongoDBManaging Social Content with MongoDB
Managing Social Content with MongoDB
 
Back to Basics Webinar 3: Schema Design Thinking in Documents
 Back to Basics Webinar 3: Schema Design Thinking in Documents Back to Basics Webinar 3: Schema Design Thinking in Documents
Back to Basics Webinar 3: Schema Design Thinking in Documents
 
Modeling JSON data for NoSQL document databases
Modeling JSON data for NoSQL document databasesModeling JSON data for NoSQL document databases
Modeling JSON data for NoSQL document databases
 
Schema Design
Schema DesignSchema Design
Schema Design
 
Schema design
Schema designSchema design
Schema design
 
Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and Hadoop
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java Developers
 
Schema Design
Schema DesignSchema Design
Schema Design
 
Mongo db 101 dc group
Mongo db 101 dc groupMongo db 101 dc group
Mongo db 101 dc group
 
Schema Design
Schema DesignSchema Design
Schema Design
 
10gen Presents Schema Design and Data Modeling
10gen Presents Schema Design and Data Modeling10gen Presents Schema Design and Data Modeling
10gen Presents Schema Design and Data Modeling
 
Aggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days MunichAggregation Framework MongoDB Days Munich
Aggregation Framework MongoDB Days Munich
 
Freeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureFreeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS Architecture
 
Schema Design
Schema DesignSchema Design
Schema Design
 

More from Uwe Friedrichsen

Timeless design in a cloud-native world
Timeless design in a cloud-native worldTimeless design in a cloud-native world
Timeless design in a cloud-native worldUwe Friedrichsen
 
Deep learning - a primer
Deep learning - a primerDeep learning - a primer
Deep learning - a primerUwe Friedrichsen
 
Life after microservices
Life after microservicesLife after microservices
Life after microservicesUwe Friedrichsen
 
The hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerThe hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerUwe Friedrichsen
 
Digitization solutions - A new breed of software
Digitization solutions - A new breed of softwareDigitization solutions - A new breed of software
Digitization solutions - A new breed of softwareUwe Friedrichsen
 
Real-world consistency explained
Real-world consistency explainedReal-world consistency explained
Real-world consistency explainedUwe Friedrichsen
 
The 7 quests of resilient software design
The 7 quests of resilient software designThe 7 quests of resilient software design
The 7 quests of resilient software designUwe Friedrichsen
 
Excavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsExcavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsUwe Friedrichsen
 
The truth about "You build it, you run it!"
The truth about "You build it, you run it!"The truth about "You build it, you run it!"
The truth about "You build it, you run it!"Uwe Friedrichsen
 
Resilient Functional Service Design
Resilient Functional Service DesignResilient Functional Service Design
Resilient Functional Service DesignUwe Friedrichsen
 
Watch your communication
Watch your communicationWatch your communication
Watch your communicationUwe Friedrichsen
 
Life, IT and everything
Life, IT and everythingLife, IT and everything
Life, IT and everythingUwe Friedrichsen
 
DevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextDevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextUwe Friedrichsen
 
Production-ready Software
Production-ready SoftwareProduction-ready Software
Production-ready SoftwareUwe Friedrichsen
 
Towards complex adaptive architectures
Towards complex adaptive architecturesTowards complex adaptive architectures
Towards complex adaptive architecturesUwe Friedrichsen
 
Conway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITConway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITUwe Friedrichsen
 
Microservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskMicroservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskUwe Friedrichsen
 
Modern times - architectures for a Next Generation of IT
Modern times - architectures for a Next Generation of ITModern times - architectures for a Next Generation of IT
Modern times - architectures for a Next Generation of ITUwe Friedrichsen
 
The Next Generation (of) IT
The Next Generation (of) ITThe Next Generation (of) IT
The Next Generation (of) ITUwe Friedrichsen
 
Why resilience - A primer at varying flight altitudes
Why resilience - A primer at varying flight altitudesWhy resilience - A primer at varying flight altitudes
Why resilience - A primer at varying flight altitudesUwe Friedrichsen
 

More from Uwe Friedrichsen (20)

Timeless design in a cloud-native world
Timeless design in a cloud-native worldTimeless design in a cloud-native world
Timeless design in a cloud-native world
 
Deep learning - a primer
Deep learning - a primerDeep learning - a primer
Deep learning - a primer
 
Life after microservices
Life after microservicesLife after microservices
Life after microservices
 
The hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerThe hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developer
 
Digitization solutions - A new breed of software
Digitization solutions - A new breed of softwareDigitization solutions - A new breed of software
Digitization solutions - A new breed of software
 
Real-world consistency explained
Real-world consistency explainedReal-world consistency explained
Real-world consistency explained
 
The 7 quests of resilient software design
The 7 quests of resilient software designThe 7 quests of resilient software design
The 7 quests of resilient software design
 
Excavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsExcavating the knowledge of our ancestors
Excavating the knowledge of our ancestors
 
The truth about "You build it, you run it!"
The truth about "You build it, you run it!"The truth about "You build it, you run it!"
The truth about "You build it, you run it!"
 
Resilient Functional Service Design
Resilient Functional Service DesignResilient Functional Service Design
Resilient Functional Service Design
 
Watch your communication
Watch your communicationWatch your communication
Watch your communication
 
Life, IT and everything
Life, IT and everythingLife, IT and everything
Life, IT and everything
 
DevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextDevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader context
 
Production-ready Software
Production-ready SoftwareProduction-ready Software
Production-ready Software
 
Towards complex adaptive architectures
Towards complex adaptive architecturesTowards complex adaptive architectures
Towards complex adaptive architectures
 
Conway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITConway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective IT
 
Microservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskMicroservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack risk
 
Modern times - architectures for a Next Generation of IT
Modern times - architectures for a Next Generation of ITModern times - architectures for a Next Generation of IT
Modern times - architectures for a Next Generation of IT
 
The Next Generation (of) IT
The Next Generation (of) ITThe Next Generation (of) IT
The Next Generation (of) IT
 
Why resilience - A primer at varying flight altitudes
Why resilience - A primer at varying flight altitudesWhy resilience - A primer at varying flight altitudes
Why resilience - A primer at varying flight altitudes
 

Recently uploaded

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
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)wesley chun
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
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 2024The Digital Insurer
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel AraĂşjo
 
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 WorkerThousandEyes
 
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 2024The Digital Insurer
 
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 BusinessPixlogix Infotech
 
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 DevelopmentsTrustArc
 
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...Drew Madelung
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
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...Enterprise Knowledge
 

Recently uploaded (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
+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...
 
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)
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
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
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
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
 
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
 
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
 
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
 
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...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
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 survive in a BASE world

  • 1. How to survive in a BASE world A practical guide for the dauntless developer Uwe Friedrichsen, codecentric AG, 2013
  • 4. A C I DAtomicity Consistency Isolation Durability
  • 5. B A S EBasically Available Soft State Eventually Consistent
  • 6. ACID • Strong consistency • Isolation • Focus on “commit” • Nested transactions • Availability? • Conservative (pessimistic) • Difficult evolution (e.g. schema) BASE • Weak consistency (stale data OK) • Availability first • Best effort • Approximate answers OK • Aggressive (optimistic) • Simpler! • Faster • Easier evolution But I think it’s a spectrum ACID vs. BASE Source: Eric Brewer, Towards Robust Distributed Systems, PODC Keynote, July-19-2000
  • 7. Consequences • No ACID properties across entities • No ACID properties across nodes • ACID properties for single entity on single node
  • 8. A (very) simple example
  • 9. customer id : long name : string book id : long title : string author : string loaned by loaned 0..1 0..n loan(customer, book) : void return(customer, book) : void booksLoaned(customer) : list of book isBookLoaned(book) : boolean Data model Actions
  • 10. Iteration #0 RDBMS – ACID – JPA
  • 11. JPA Entity Class Customer @Entity public class Customer { @Id @GeneratedValue private long id; private String name; @OneToMany(mappedBy = "customer") private final List<Book> loanedBooks; <Methods> }
  • 12. JPA Entity Class Book @Entity public class Book { @Id @GeneratedValue private long id; private String title; private String author; private Customer customer; <Methods> }
  • 13. Database model Foreign Key to CUSTOMER.ID TABLE CUSTOMER ID NAME TABLE BOOK ID TITLE AUTHOR CUSTOMER (FK)
  • 14. Action „loan“ using JPA public void loan(long customerId, long bookId) { <Get EntityManager> em.getTransaction().begin(); <Read customer and book from database> customer.getLoanedBooks().add(book); book.setCustomer(customer); em.persist(customer); em.persist(book); em.getTransaction().commit(); <Cleanup> } Same for action „return“
  • 15. Action „isBookLoaned“ using JPA public boolean isBookLoaned(long bookId) { <Get EntityManager> Query q = em.createQuery("SELECT b FROM Book b WHERE b.id = :id"); q.setParameter("id", bookId); Book book = (Book) q.getSingleResult(); return book.getCustomer() != null; }
  • 16. Action „booksLoaned“ using JPA public List<Book> booksLoaned(long customerId) { <Get EntityManager> Query q = em.createQuery("SELECT c FROM Customer c WHERE c.id = :id"); q.setParameter("id", customerId); Customer customer = (Customer) q.getSingleResult(); return customer.getLoanedBooks(); } Boils down to an implicitly executed SQL query that looks like SELECT … FROM BOOK WHERE CUSTOMERID = <customerId>
  • 17. Mutating action • begin transaction • do required changes • commit Non-mutating action • create query • execute query • navigate in result set (implicitly executing additional queries if required) Wrapup ACID model
  • 18. Iteration #1 NoSQL – BASE – naĂŻve
  • 19. Mutating action • begin transaction • do required changes • commit Non-mutating action • create query • execute query • navigate in result set (implicitly executing additional queries if required) NaĂŻve BASE model ???
  • 20. Data model Customer TABLE CUSTOMER ID NAME Book TABLE BOOK ID TITLE AUTHOR CUSTOMER (FK) { "id" : <id>, "name" : "<name>" } { "id" : <id>, "title" : "<title>", "author" : "<author>", "customerId" : <id> }
  • 21. JPA Entity Class Customer @Entity public class Customer { @Id @GeneratedValue private long id; private String name; @OneToMany(mappedBy = "customer") private final List<Book> loanedBooks; <Methods> } Need to take care of ID generation ourselves Gone for the moment (naĂŻve approach)
  • 22. Class Customer public class Customer { private long id; private String name; <Methods> }
  • 23. JPA Entity Class Book @Entity public class Book { @Id @GeneratedValue private long id; private String title; private String author; private Customer customer; <Methods> } Need to take care of ID generation ourselves Gone for the moment (naĂŻve approach)
  • 24. Class Book public class Book { private long id; private String title; private String author; private long customerId; <Methods> } Only the ID
  • 25. Action „loan“, „return“ & „isBookLoaned“ public void loan(long customerId, long bookId) { Book book = readBook(bookId); book.setCustomerId(customerId); writeBook(book); } public void return(long customerId, long bookId) { Book book = readBook(bookId); book.setCustomerId(0L); writeBook(book); } public boolean isBookLoaned(long bookId) { Book book = readBook(bookId); return book.getCustomerId() > 0L; }
  • 26. readBook private Book readBook(long id) { String json = readBookFromDb(id); return toBook(json); } private Book toBook(String json) { JSONObject jo = new JSONObject(json); Book b = new Book(jo.getLong("id"), jo.getString("title"), jo.getString("author"), jo.getLong("customerId")); return b; } Same for „readCustomer“ and „toCustomer“
  • 27. writeBook private void writeBook(Book b) { long key = b.getId(); String json = fromBook(b); writeBookToDb(key, json); } private String fromBook(Book b) { JSONObject jo = new JSONObject(); jo.put("id", b.getId()); jo.put("title", c.getTitle()); jo.put("author", c.getAuthor()); jo.put("customerId", b.getCustomerId()); return jo.toString(); } Same for „writeCustomer“ and „fromCustomer“
  • 28. Action „booksLoaned“ public List<Book> booksLoaned(long customerId) { List<Book> loanedBooks = new ArrayList<Book>(); Iterator<Book> it = readAllBooks(); for (Book b : it) { if (book.getCustomerId() == customerId) { loanedBooks.add(b); } } return loanedBooks; } private Iterator<Book> readAllBooks() { DBIterator dbi = readAllBooksFromDb(); // Iterator<String> (json) return new BookIterator(dbi); }
  • 29. BookIterator public class BookIterator implements Iterator<Book> { private final DBIterator dbi; public BookIterator(DBIterator dbi) { this.dbi = dbi; } @Override public boolean hasNext() { return dbi.hasNext(); } @Override public Book next() { return toBook(dbi.next()); } @Override public void remove() { throw new UnsupportedOperationException(); } }
  • 31. Assume the following code sequence loan(2312L, 4711L); boolean isLoaned = isBookLoaned(4711L); Question: Which value has isLoaned? Quick exercise
  • 32. Alternative #1 Replica Node 1 Replica Node 3 Client replicate 2 loan1 isLoaned 3 Replica Node 2 
  • 33. Alternative #2 Replica Node 1 Replica Node 3 Client replicate 3 loan1 isLoaned 2 Replica Node 2 
  • 34. Read your own writes Solution #1
  • 35. Read your own writes Replica Node 1 Replica Node 3 Client replicate ? loan1 isLoaned 2 Replica Node 2
  • 37. Read from master Master Slave 2 Client replicate ? loan1 isLoaned 2 Slave 1
  • 38. Quorum • W > N/2 • R + W > N Solution #3
  • 39. readBook & writeBook private Book readBook(long id) { String json = readBookFromDb(id, READ_QUORUM); return toBook(json); } private void writeBook(Book b) { long key = b.getId(); String json = fromBook(b); writeBookToDb(key, json, WRITE_QUORUM); } Same for „readCustomer“ and „writeCustomer“
  • 41. Assume the following code sequence boolean isLoaned = isBookLoaned(4711L); Question: What do you get? Quick exercise
  • 42. isBookLoaned(4711L) public boolean isBookLoaned(4711L) { Book book = readBook(4711L); return book.getCustomerId() > 0L; } private Book readBook(4711L) { String json = readBookFromDb(4711L); return toBook(json); } private Book toBook(String json) { JSONObject jo = new JSONObject(json); Book b = new Book(jo.getLong("id"), jo.getString("title"), jo.getString("author"), jo.getLong("customerId")); return b; } Expects a “normal” book JSON
  • 43. … but your JSON looks like this { "siblings" : [ { "id" : 4711L, "title" : "The Catcher in the Rye", "author" : "J. D. Salinger", "customerId" : 2312L }, { "id" : 4711L, "title" : "The Catcher in the Rye", "author" : "J. D. Salinger", "customerId" : 0L } ] }
  • 44. Leave the decision to the caller Solution #1
  • 46. Extended JSON data model Customer: { "id" : <id>, "name" : "<name>", "timestamp" : <timestamp> } Book: { "id" : <id>, "title" : "<title>", "author" : "<author>", "customerId" : <id>, "timestamp" : <timestamp> }
  • 47. Domain Classes public class Customer { private Long id; private String name; <Methods> } public class Book { private long id; private String title; private String author; private long customerId; <Methods> } Timestamp not required in the domain classes
  • 48. fromBook private String fromBook(Book b) { JSONObject jo = new JSONObject(); jo.put("id", b.getId()); jo.put("title", c.getTitle()); jo.put("author", c.getAuthor()); jo.put("customerId", b.getCustomerId()); jo.put("timestamp", System.currentTimeMillis()); return jo.toString(); } Same for „fromCustomer“ Timestamp added in mapping
  • 49. toBook private Book toBook(String json) { JSONObject jo = new JSONObject(resolveBook(json)); Book b = new Book(jo.getLong("id"), jo.getString("title"), jo.getString("author"), jo.getLong("customerId")); return b; } Same for „toCustomer“
  • 50. resolveBook private String resolveBook(String json) { JSONObject jo = new JSONObject(json); JSONArray siblings = jo.optJSONArray("siblings"); if (siblings == null) { return json; } int index = 0; long timestamp = 0L for (int i = 0; i < siblings.length(); i++) { long t = siblings.getJSONObject(i).getLong("timestamp"); if (t > timestamp) { index = i; timestamp = t; } } return siblings.getJSONObject(index).toString(); }
  • 51. Conflict-free replicated data types Solution #3
  • 53. Assume the following method to retrieve the number of books a customer has loaned public int numberOfBooksLoaned(long cId) { return booksLoaned(cId).size(); } Question: How is the performance? Quick exercise
  • 54. Remember the implementation public List<Book> booksLoaned(long customerId) { List<Book> loanedBooks = new ArrayList<Book>(); Iterator<Book> it = readAllBooks(); for (Book b : it) { if (book.getCustomerId() == customerId) { loanedBooks.add(b); } } return loanedBooks; } private Iterator<Book> readAllBooks() { DBIterator dbi = readAllBooksFromDb(); // Iterator<String> (json) return new BookIterator(dbi); } Reads all book entities distributed across all nodes
  • 56. Re-implementation using indices public List<Book> booksLoaned(long customerId) { List<Book> loanedBooks = new ArrayList<Book>(); Iterator<Book> it = readAllBooksLoanedByACustomer(customerId); for (Book b : it) { loanedBooks.add(b); } return loanedBooks; } private Iterator<Book> readAllBooksLoanedByACustomer(long customerId) { DBIterator dbi = readAllBooksUsingSecondaryIndexFromDb(long customerId); return new BookIterator(dbi); }
  • 57. • Only works on ACID nodes • Duplicates while rebalancing • Partial answers if node is down Tradeoffs of indices
  • 58. … but actually you are interested in a property that logically belongs to a single customer
  • 60. Denormalized Customer entity { "id" : <id>, "name" : "<name>", "loanedBooks" : [ { "id" : <id>, "title" : "<title>", "author" : "<author>" }, ... ], "timestamp" : <timestamp> } Can be empty
  • 61. Denormalized Book entity { "id" : <id>, "title" : "<title>", "author" : "<author>", "loanedBy" : { "id" : <id>, "name" : "<name>" }, "timestamp" : <timestamp> } Optional value
  • 62. Denormalized Customer domain class public class Customer { private Long id; private String name; private List<BookRef> loanedBooks; <Methods> } public class BookRef { object private Long id; private String title; private String author; <Methods> } Here we go again
  • 63. Denormalized Book domain class public class Book { private Long id; private String title; private String author; private CustomerRef customer; <Methods> } public class CustomerRef { private Long id; private String name; <Methods> } Here we go again
  • 64. Actions „loan“ & „return“ public void loan(long customerId, long bookId) { Customer customer = readCustomer(customerId); Book book = readBook(bookId); customer.getLoanedBooks().add(new BookRef(book)); book.setCustomer(new CustomerRef(customer)); writeCustomer(customer); writeBook(book); } public void return(long customerId, long bookId) { Customer customer = readCustomer(customerId); Book book = readBook(bookId); customer.getLoanedBooks().remove(new BookRef(book)); book.setCustomer(null); writeCustomer(customer); writeBook(book); } Also mutates the customer
  • 65. Actions „booksLoaned“ & „isBookLoaned“ public List<BookRef> booksLoaned(long customerId) { Customer customer = readCustomer(customerId); return customer.getLoanedBooks(); } public boolean isBookLoaned(long bookId) { Book book = readBook(bookId); return book.getCustomer() != null; } Only one read required Check becomes more expressive Method “readAllBooks” not required anymore in this scenario
  • 66. fromCustomer private String fromCustomer(Customer c) { JSONObject jo = new JSONObject(); jo.put("id", c.getId()); jo.put("name", c.getName()); JSONArray ja = new JSONArray(); for (BookRef b : c.getLoanedBooks()) { JSONObject jb = new JSONObject(); jb.put("id", b.getId()); jb.put("title", c.getTitle()); jb.put("author", c.getAuthor()); ja.put(jb); } jo.put("loanedBooks", ja); jo.put("timestamp", System.currentTimeMillis()); return jo.toString(); } Also map book references
  • 67. toCustomer private Customer toCustomer(String json) { JSONObject jo = new JSONObject(json); JSONArray ja = jo.getJSONArray("loanedBooks"); List<BookRef> loanedBooks = new ArrayList<BookRef>(); for (int i = 0; i < ja.length(); i++) { JSONObject jb = ja.getJSONObject(i); BookRef b = new BookRef(jb.getLong("id"), jb.getString("title"), jb.getString("author")); loanedBooks.add(b); } Customer c = new Customer(jo.getLong("id"), jo.getString("name"), loanedBooks); return c; } Also map book references
  • 68. fromBook private String fromBook(Book b) { JSONObject jo = new JSONObject(); jo.put("id", b.getId()); jo.put("title", c.getTitle()); jo.put("author", c.getAuthor()); if (c.getCustomer() != null) { JSONObject jc = new JSONObject(); jc.put("id", c.getCustomer().getId()); jc.put("name", c.getCustomer().getName()); jo.put("loanedBy", jc); } jo.put("timestamp", System.currentTimeMillis()); return jo.toString(); } Also map customer reference
  • 69. toBook private Book toBook(String json) { JSONObject jo = new JSONObject(json); CustomerRef c = null; JSONObject jc = jo.optJSONObject("loanedBy"); if (jc != null) { c = new CustomerRef(jc.getLong("id"), jc.getString("name")); } Book b = new Book(jo.getLong("id"), jo.getString("title"), jo.getString("author"), c); return b; } Also map customer reference
  • 70. • All data within one entity • Coarse grained entities • Often huge read speedups • No OR-Mapper equivalent • Can result in inconsistencies across entities Wrapup denormalization
  • 72. Assume the following code sequence loan(2312L, 4711L); long bookId = readCustomer(2312L) .getLoanedBooks().get(0).getId(); long customerId = readBook(4711L) .getCustomer().getId(); Question: What do you get? Quick exercise
  • 73. Remember the implementation public void loan(2312L, 4711L) { Customer customer = readCustomer(2312L); Book book = readBook(4711L); customer.getLoanedBooks().add(new BookRef(book)); book.setCustomer(new CustomerRef(customer)); writeCustomer(customer); writeBook(book); } This call fails
  • 74. Leads to the following entity state { "id" : 2312L, "name" : "Uwe Friedrichsen", "loanedBooks" : [ { "id" : 4711L, "title" : "The Catcher in the Rye", "author" : "J. D. Salinger" } ], "timestamp" : <timestamp> } { "id" : 4711L, "title" : "The Catcher in the Rye", "author" : "J. D. Salinger", "timestamp" : <timestamp> }
  • 76. Actions „loan“ & „return“ public void loan(long customerId, long bookId) { Customer customer = readCustomer(customerId); Book book = readBook(bookId); customer.getLoanedBooks().add(new BookRef(book)); book.setCustomer(new CustomerRef(customer)); writeBook(book); writeCustomer(customer); } public void return(long customerId, long bookId) { Customer customer = readCustomer(customerId); Book book = readBook(bookId); customer.getLoanedBooks().remove(new BookRef(book)); book.setCustomer(null); writeBook(book); writeCustomer(customer); } Switched write order
  • 77. resolveIfRequired private void resolveIfRequired(Customer c, Book b) { BookRef br = new BookRef(b.getId(), b.getTitle(), b.getAuthor()); if (!c.getLoanedBooks().contains(br)) { c.getLoanedBooks.add(br); } } // some code that (for some reason) reads both related entities ... Book book = readBook(bookId); Customer customer = null; If (book.getCustomer() != null) { readCustomer(book.getCustomer().getId()); resolveIfRequired(customer, book); } // Do stuff with customer and book ...
  • 78. On-the-fly resolver with write-back (“read repair”) Solution #2
  • 79. resolveIfRequired private void resolveIfRequired(Customer c, Book b) { BookRef br = new BookRef(b.getId(), b.getTitle(), b.getAuthor()); if (!c.getLoanedBooks().contains(br)) { c.getLoanedBooks.add(br); writeCustomer(c); } } Best effort principle
  • 80. Consistency crawler Compensating actions Change journal … Advanced solutions ???
  • 81. Wrap-up • BASE is different • New challenges for a developer • Some databases promise to hide BASE … … but you can‘t fool the laws of distribution • Inconsistencies will happen – be prepared
  • 82. The real world is also BASE Welcome to reality … ;-)