Créer une base NoSQL en 1 heure

A
Amaury BouchardCTO à Fine Media
Créer un serveur noSQL
en une heure
Bases noSQL
Bibliothèques utilisées
Présentation AngstromDB
Étude de code
Benchmark & évolutions
Créer un serveur noSQL
Base noSQL
Aller plus loin
Scalabilité horizontale
Haute disponibilité
Big Data
S'affranchir
Modèle relationnel
Transactions ACID
Principe général
Types de bases noSQL
Clé-valeur Document Colonne Graph
Dynamo
Riak
Redis
Voldemort
Tokyo Tyrant
MemcacheDB
FoundationDB
MongoDB
CouchDB
CouchBase
HyperDex
RethinkDB
Cassandra
Hadoop / Hbase
Accumulo
Neo4J
Allegro
Virtuoso
InfoGrid
Bibliothèques
de programmation
Le successeur de ZeroMQ
Bibliothèque réseau avec des
super-pouvoirs
Nanomsg
Gestion de files de messages
Protocole spécifique
14 langages supportés
Redéfinition des concepts réseau
Nanomsg
Méthodes de transport
Inter-threads inproc
Inter-processus ipc
Inter-machines tcp
Découplage du sens de connexion
ServeurClient
Découplage du sens de connexion
ServeurClient
Socket multi-connexion
ServeurClient
Client
Client
port A
port B
Connexion REQ/REP
ServeurClient
REQ
Connexion REQ/REP
ServeurClient
REP
Connexion PUSH/PULL
ServeurClient
PUSH
Connexion PUSH/PULL
ServeurClient
PULL
Connexion PUB/SUB
Client
PUB
Serveur
Client
Client
Connexion PUB/SUB
ClientServeur
Client
Client
SUB
SUB
SUB
Load-balancing
ClientServeur
Client
Client
PULL
PUSH
Load-balancing
ClientServeur
Client
Client
PULLPUSH
Load-balancing
ClientServeur
Client
Client
PULL
PUSH
Bus
Client
Client
Client
Client
Bus
Client Client
Client
Client
Stockage paires clé-valeur multivaluées
Persistance sur disque, mapping RAM
Transactionnel (1 thread d'écriture)
Au cœur de OpenLDAP
LMDB (LightningDB)
Débit
Latence
ops / sec.
microsec.
HyperDex : LMDB vs LevelDB
Présentation
AngstromDB
Serveur paires clé-valeur
Codé en C
Basé sur des bibliothèques reconnues
Protocole binaire
Aucun contrôle d'erreur
Implémentation naïve
API très simple
PUT
Ajout ou mise-à-jour de clé
GET
Retourne une valeur
DELETE
Efface une clé
Protocole : DELETE
2
cmd taille
clé
clé
1 1 1 à 255 octets
Requête
Réponse 1
statut
1
Protocole : GET
3
cmd taille
clé
clé
1 1 1 à 255 octets
Requête
Réponse 1
statut taille
données
données
1 4 0 à 4 GO
Protocole : PUT
1
cmd taille clé clé
1 1 1 à 255 octets
Requête
Réponse 1
statut
taille données données
1
4 0 à 4 GO
Multi-threadé
Thread principal
Attend les nouvelles connexions
Threads de communication
Un thread par client connecté
Thread d'écriture
Pas d'écriture concurrente
Thread principal
Threads de communication
LMDB
Thread
d'écriture
Étude de code
github.com/Amaury/AngstromDB ↩
↪ /tree/master/src
Démarrage
/*
* db Pointer to the database environment.
* socket Socket descriptor for incoming connections.
* threads_socket Nanomsg socket for threads communication.
* writer_tid ID of the writer thread.
* comm_threads Array of communication threads.
*/
typedef struct angstrom_s {
MDB_env *db;
int socket;
int threads_socket;
pthread_t writer_tid;
struct comm_thread_s *comm_threads;
} angstrom_t;
/*
* tid Thread's identifier.
* angstrom Pointer to the server's structure.
* client_sock Socket used to communicate with the client.
* writer_sock Nanomsg socket to send data to the writer. */
typedef struct comm_thread_s {
pthread_t tid;
angstrom_t *angstrom;
int client_sock;
int writer_sock;
} comm_thread_t;
angstrom.h
Démarrage
int main() {
angstrom_t *angstrom;
int i;
// server init
angstrom = calloc(1, sizeof(angstrom_t));
angstrom->socket = angstrom->threads_socket = -1;
angstrom->comm_threads = calloc(NBR_THREADS,
sizeof(comm_thread_t));
// open the database
angstrom->db = database_open(DEFAULT_DB_PATH,
DEFAULT_MAPSIZE, NBR_THREADS);
// create the nanomsg socket for threads communication
angstrom->threads_socket = nn_socket(AF_SP, NN_PUSH);
nn_bind(angstrom->threads_socket, ENDPOINT_THREADS_SOCKET);
// create the writer thread
pthread_create(&angstrom->writer_tid, NULL,
thread_writer_loop, angstrom);
main.c
Démarrage
int main() {
angstrom_t *angstrom;
int i;
// server init
angstrom = calloc(1, sizeof(angstrom_t));
angstrom->socket = angstrom->threads_socket = -1;
angstrom->comm_threads = calloc(NBR_THREADS,
sizeof(comm_thread_t));
// open the database
angstrom->db = database_open(DEFAULT_DB_PATH,
DEFAULT_MAPSIZE, NBR_THREADS);
// create the nanomsg socket for threads communication
angstrom->threads_socket = nn_socket(AF_SP, NN_PUSH);
nn_bind(angstrom->threads_socket, ENDPOINT_THREADS_SOCKET);
// create the writer thread
pthread_create(&angstrom->writer_tid, NULL,
thread_writer_loop, angstrom);
main.c
"inproc://threads_socket"
Démarrage
// create communication threads
for (i = 0; i < NBR_THREADS; i++) {
comm_thread_t *thread = &(angstrom->comm_threads[i]);
thread->client_sock = -1;
thread->angstrom = angstrom;
pthread_create(&thread->tid, 0, thread_comm_loop,
thread);
pthread_detach(thread->tid);
}
// create listening socket
angstrom->socket = _create_listening_socket(DEFAULT_PORT);
// server loop
_main_thread_loop(angstrom);
return (0);
}
main.c
Démarrage
MDB_env *database_open(const char *path, size_t mapsize,
unsigned int nbr_threads) {
MDB_env *env = NULL;
mdb_env_create(&env);
mdb_env_set_mapsize(env, mapsize);
mdb_env_set_maxreaders(env, nbr_threads);
mdb_env_open(env, path, 0, 0664);
return (env);
}
database.c
Démarrage
static int _create_listening_socket(unsigned short port) {
int sock;
struct sockaddr_in addr;
unsigned int addr_size;
const int on = 1;
// create the socket
sock = socket(AF_INET, SOCK_STREAM, 0);
// some options
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
sizeof(on));
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&on,
sizeof(on));
// binding to any interface
addr_size = sizeof(addr);
bzero(&addr, addr_size);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
bind(sock, (struct sockaddr*)&addr, addr_size);
listen(sock, SOMAXCONN);
return (sock);
}
main.c
Nouvelle connexion
static void _main_thread_loop(angstrom_t *angstrom) {
int fd;
struct sockaddr_in addr;
unsigned int addr_size;
const int on = 1;
addr_size = sizeof(addr);
for (; ; ) {
bzero(&addr, addr_size);
// accept a new connection
if ((fd = accept(angstrom->socket,
(struct sockaddr*)&addr,
&addr_size)) < 0) {
continue ;
}
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on,
sizeof(on));
// send the file descriptor number to comm threads
nn_send(angstrom->threads_socket, &fd, sizeof(fd), 0);
}
}
main.c
Nouvelle connexion
void *thread_comm_loop(void *param) {
comm_thread_t *thread = param;
int in_sock;
// opening a connection to the writer thread
thread->writer_sock = nn_socket(AF_SP, NN_PUSH);
nn_connect(thread->writer_sock, ENDPOINT_WRITER_SOCKET);
// opening a connection to the main thread
in_sock = nn_socket(AF_SP, NN_PULL);
nn_connect(in_sock, ENDPOINT_THREADS_SOCKET);
// loop to process new connections
for (; ; ) {
// waiting for a new connection to handle
nn_recv(in_sock, &thread->client_sock, sizeof(int), 0);
// process connection
_process_connection(thread);
}
return (NULL);
}
thread_com
munication.c
Nouvelle connexion
void *thread_comm_loop(void *param) {
comm_thread_t *thread = param;
int in_sock;
// opening a connection to the writer thread
thread->writer_sock = nn_socket(AF_SP, NN_PUSH);
nn_connect(thread->writer_sock, ENDPOINT_WRITER_SOCKET);
// opening a connection to the main thread
in_sock = nn_socket(AF_SP, NN_PULL);
nn_connect(in_sock, ENDPOINT_THREADS_SOCKET);
// loop to process new connections
for (; ; ) {
// waiting for a new connection to handle
nn_recv(in_sock, &thread->client_sock, sizeof(int), 0);
// process connection
_process_connection(thread);
}
return (NULL);
}
thread_com
munication.c
"inproc://writer_socket"
"inproc://threads_socket"
Nouvelle connexion
static void _process_connection(comm_thread_t *thread) {
uint8_t cmd;
// loop on incoming requests
for (; ; ) {
// read command byte
if (read(thread->client_sock, &cmd, sizeof(cmd)) <= 0) {
close(thread->client_sock);
break;
}
// interpret command
switch (cmd) {
case PROTO_PUT:
command_put(thread);
break;
case PROTO_DELETE:
command_del(thread);
break;
case PROTO_GET:
command_get(thread);
break;
}
}
}
thread_com
munication.c
Lecture de données
void command_get(comm_thread_t *thread) {
uint8_t key_size, response = PROTO_OK;
uint32_t value_size;
MDB_val key, value;
// read key length
read(thread->client_sock, &key_size, sizeof(key_size));
// read key data
key.mv_data = malloc(key_size);
read(thread->client_sock, key.mv_data, key_size);
// get data
key.mv_size = (size_t)key_size;
database_get(thread->angstrom->db, &key, &value);
// send response to the client
write(thread->client_sock, &response, sizeof(response));
value_size = htonl((uint32_t)value.mv_size);
write(thread->client_sock, &value_size, sizeof(value_size));
if (value_size)
write(thread->client_sock, value.mv_data, value.mv_size);
}
command_
get.c
Lecture de données
void database_get(MDB_env *db, MDB_val *key, MDB_val *value) {
MDB_dbi dbi;
MDB_txn *txn;
// transaction init
mdb_txn_begin(db, NULL, MDB_RDONLY, &txn);
// open database in read-write mode
mdb_dbi_open(txn, NULL, 0, &dbi);
// get data
if (mdb_get(txn, dbi, key, value))
bzero(value, sizeof(*value));
// end of transaction
mdb_txn_abort(txn);
// close database
mdb_dbi_close(db, dbi);
}
database.c
Thread d'écriture
/*
* type Type of action (WRITE_PUT, WRITE_DEL).
* key Size and content of the key.
* value Size and content of the value.
*/
typedef struct writer_msg_s {
enum {
WRITE_PUT,
WRITE_DEL
} type;
MDB_val key;
MDB_val value;
} writer_msg_t;
angstrom.h
Thread d'écriture
void *thread_writer_loop(void *param) {
angstrom_t *angstrom = param;
int socket;
// create the nanomsg socket for threads communication
socket = nn_socket(AF_SP, NN_PULL);
nn_bind(socket, ENDPOINT_WRITER_SOCKET);
// loop to process new connections
for (; ; ) {
writer_msg_t *msg;
// waiting for a new connection to handle
if (nn_recv(socket, &msg, sizeof(writer_msg_t*), 0) < 0)
continue;
// processing
switch (msg->type) {
case WRITE_PUT:
database_put(angstrom->db, &msg->key, &msg->value);
break;
case WRITE_DEL:
database_del(angstrom->db, &msg->key);
break;
}
thread_
writer.c
Thread d'écriture
void *thread_writer_loop(void *param) {
angstrom_t *angstrom = param;
int socket;
// create the nanomsg socket for threads communication
socket = nn_socket(AF_SP, NN_PULL);
nn_bind(socket, ENDPOINT_WRITER_SOCKET);
// loop to process new connections
for (; ; ) {
writer_msg_t *msg;
// waiting for a new connection to handle
if (nn_recv(socket, &msg, sizeof(writer_msg_t*), 0) < 0)
continue;
// processing
switch (msg->type) {
case WRITE_PUT:
database_put(angstrom->db, &msg->key, &msg->value);
break;
case WRITE_DEL:
database_del(angstrom->db, &msg->key);
break;
}
thread_
writer.c
"inproc://writer_socket"
Thread d'écriture
// free data
if (msg->key.mv_data)
free(msg->key.mv_data);
if (msg->value.mv_data)
free(msg->value.mv_data);
free(msg);
}
return (NULL);
}
thread_
writer.c
Effacement de clé
void command_delete(comm_thread_t *thread) {
uint8_t key_size, response = PROTO_OK;
void *key;
writer_msg_t *msg;
// read key length
read(thread->client_sock, &key_size, sizeof(key_size));
// read key data
key = malloc(key_size);
read(thread->client_sock, key, key_size);
// create message
msg = calloc(1, sizeof(writer_msg_t));
msg->type = WRITE_DEL;
msg->key.mv_size = (size_t)key_size;
msg->key.mv_data = key;
// send the message to the writer thread
nn_send(thread->writer_sock, &msg, sizeof(msg), 0);
// send response to the client
write(thread->client_sock, &response, sizeof(response));
}
command_
delete.c
Effacement de clé
void database_del(MDB_env *db, MDB_val *key) {
MDB_dbi dbi;
MDB_txn *txn;
// transaction init
mdb_txn_begin(db, NULL, 0, &txn);
// open database in read-write mode
mdb_dbi_open(txn, NULL, 0, &dbi);
// delete key
mdb_del(txn, dbi, key, NULL);
// close database
mdb_dbi_close(db, dbi);
// transaction commit
mdb_txn_commit(txn);
}
database.c
Ajout / mise-à-jour de clé
void command_put(comm_thread_t *thread) {
uint8_t key_size, response = PROTO_OK;
void *key, *value = NULL;
uint32_t value_size;
writer_msg_t *msg;
// read key length
read(thread->client_sock, &key_size, sizeof(key_size));
// read key data
key = malloc(key_size);
read(thread->client_sock, key, key_size);
// read value length
read(thread->client_sock, &value_size, sizeof(value_size));
value_size = ntohl(value_size);
if (value_size > 0) {
// read value data
value = malloc(value_size);
read(thread->client_sock, value, value_size);
}
command_
put.c
Ajout / mise-à-jour de clé
// create message
msg = malloc(sizeof(writer_msg_t));
msg->type = WRITE_PUT;
msg->key.mv_size = (size_t)key_size;
msg->key.mv_data = key;
msg->value.mv_size = (size_t)value_size;
msg->value.mv_data = value;
// send the message to the writer thread
nn_send(thread->writer_sock, &msg, sizeof(msg), 0);
// send response to the client
write(thread->client_sock, &response, sizeof(response));
}
command_
put.c
Ajout / mise-à-jour de clé
void database_put(MDB_env *db, MDB_val *key, MDB_val *value) {
MDB_dbi dbi;
MDB_txn *txn;
// transaction init
mdb_txn_begin(db, NULL, 0, &txn);
// open database in read-write mode
mdb_dbi_open(txn, NULL, 0, &dbi);
// put data
mdb_put(txn, dbi, key, value, 0);
// close database
mdb_dbi_close(db, dbi);
// transaction commit
mdb_txn_commit(txn);
}
database.c
Créer une base NoSQL en 1 heure
cloc
Language files comment code
-------------------------------------------------
C 7 132 212
C Header 1 111 55
make 1 13 27
-------------------------------------------------
SUM: 9 256 294
sloccount
Schedule Estimate, Years (Months) = 0.17 (2.06)
Total Estimated Cost to Develop = $ 6,753
Benchmark
Base Écritures Lectures
AngstromDB 22 ms 55 ms
Couchbase 25 ms 22 ms
Redis 29 ms 30 ms
MongoDB 39 ms 27 ms
45 écritures / lectures séquentielles de données représentatives
Améliorations
possibles
Réduire les appels systèmes !
Bufferiser les lectures réseau
Regrouper les écritures réseau
Facile à tester (sendmsg vs write)
Pour commencer
Benchmark
Base Écritures Lectures
AngstromDB 22 ms 55 ms
AngstromDB 22 ms 26 ms
Couchbase 25 ms 22 ms
Redis 29 ms 30 ms
MongoDB 39 ms 27 ms
Compression à la volée (Zippy)
Sérialisation de données (MsgPack)
Transactions en lecture
… Mono-processus asynchrone ?
Pour aller plus loin
geek-directeur-technique.com
github.com/Amaury/AngstromDB
amaury@amaury.net
@geekcto
1 sur 64

Recommandé

ZeroMQ Is The Answer par
ZeroMQ Is The AnswerZeroMQ Is The Answer
ZeroMQ Is The AnswerIan Barber
114K vues58 diapositives
ZeroMQ: Messaging Made Simple par
ZeroMQ: Messaging Made SimpleZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made SimpleIan Barber
4.6K vues36 diapositives
ZeroMQ Is The Answer: DPC 11 Version par
ZeroMQ Is The Answer: DPC 11 VersionZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 VersionIan Barber
1.7K vues50 diapositives
ZeroMQ Is The Answer: PHP Tek 11 Version par
ZeroMQ Is The Answer: PHP Tek 11 VersionZeroMQ Is The Answer: PHP Tek 11 Version
ZeroMQ Is The Answer: PHP Tek 11 VersionIan Barber
6.2K vues50 diapositives
How to stand on the shoulders of giants par
How to stand on the shoulders of giantsHow to stand on the shoulders of giants
How to stand on the shoulders of giantsIan Barber
3.6K vues32 diapositives
Redis & ZeroMQ: How to scale your application par
Redis & ZeroMQ: How to scale your applicationRedis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your applicationrjsmelo
23.4K vues33 diapositives

Contenu connexe

Tendances

PHP Backdoor: The rise of the vuln par
PHP Backdoor: The rise of the vulnPHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vulnSandro Zaccarini
457 vues26 diapositives
Debugging: Rules & Tools par
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & ToolsIan Barber
11.8K vues67 diapositives
On UnQLite par
On UnQLiteOn UnQLite
On UnQLitecharsbar
6.4K vues21 diapositives
C99.php par
C99.phpC99.php
C99.phpveng33k
1.5K vues68 diapositives
Asynchronous I/O in PHP par
Asynchronous I/O in PHPAsynchronous I/O in PHP
Asynchronous I/O in PHPThomas Weinert
8.2K vues22 diapositives
React PHP: the NodeJS challenger par
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challengervanphp
6.7K vues35 diapositives

Tendances(20)

Debugging: Rules & Tools par Ian Barber
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
Ian Barber11.8K vues
On UnQLite par charsbar
On UnQLiteOn UnQLite
On UnQLite
charsbar6.4K vues
C99.php par veng33k
C99.phpC99.php
C99.php
veng33k1.5K vues
React PHP: the NodeJS challenger par vanphp
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challenger
vanphp6.7K vues
C99 par sifo12
C99C99
C99
sifo121.1K vues
Modern Getopt for Command Line Processing in Perl par Nova Patch
Modern Getopt for Command Line Processing in PerlModern Getopt for Command Line Processing in Perl
Modern Getopt for Command Line Processing in Perl
Nova Patch1.5K vues
Smolder @Silex par Jeen Lee
Smolder @SilexSmolder @Silex
Smolder @Silex
Jeen Lee1.1K vues
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo par Masahiro Nagano
Introduction to CloudForecast / YAPC::Asia 2010 TokyoIntroduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Masahiro Nagano11.2K vues
Any event intro par qiang
Any event introAny event intro
Any event intro
qiang1.9K vues
Meet up symfony 16 juin 2017 - Les PSR par Julien Vinber
Meet up symfony 16 juin 2017 -  Les PSRMeet up symfony 16 juin 2017 -  Les PSR
Meet up symfony 16 juin 2017 - Les PSR
Julien Vinber195 vues

En vedette

De 0 à 10 millions de visiteurs uniques avec les moyens d'une startup par
De 0 à 10 millions de visiteurs uniques avec les moyens d'une startupDe 0 à 10 millions de visiteurs uniques avec les moyens d'une startup
De 0 à 10 millions de visiteurs uniques avec les moyens d'une startupAmaury Bouchard
4.7K vues48 diapositives
PyCon 2015 Belarus Andrii Soldatenko par
PyCon 2015 Belarus Andrii SoldatenkoPyCon 2015 Belarus Andrii Soldatenko
PyCon 2015 Belarus Andrii SoldatenkoAndrii Soldatenko
2.2K vues28 diapositives
SeleniumCamp 2015 Andrii Soldatenko par
SeleniumCamp 2015 Andrii SoldatenkoSeleniumCamp 2015 Andrii Soldatenko
SeleniumCamp 2015 Andrii SoldatenkoAndrii Soldatenko
5.1K vues37 diapositives
PyCon Ukraine 2014 par
PyCon Ukraine 2014PyCon Ukraine 2014
PyCon Ukraine 2014Andrii Soldatenko
2.3K vues23 diapositives
PyCon Russian 2015 - Dive into full text search with python. par
PyCon Russian 2015 - Dive into full text search with python.PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.Andrii Soldatenko
4.5K vues47 diapositives
Practical continuous quality gates for development process par
Practical continuous quality gates for development processPractical continuous quality gates for development process
Practical continuous quality gates for development processAndrii Soldatenko
6.5K vues44 diapositives

En vedette(7)

De 0 à 10 millions de visiteurs uniques avec les moyens d'une startup par Amaury Bouchard
De 0 à 10 millions de visiteurs uniques avec les moyens d'une startupDe 0 à 10 millions de visiteurs uniques avec les moyens d'une startup
De 0 à 10 millions de visiteurs uniques avec les moyens d'une startup
Amaury Bouchard4.7K vues
PyCon Russian 2015 - Dive into full text search with python. par Andrii Soldatenko
PyCon Russian 2015 - Dive into full text search with python.PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.
Andrii Soldatenko4.5K vues
Practical continuous quality gates for development process par Andrii Soldatenko
Practical continuous quality gates for development processPractical continuous quality gates for development process
Practical continuous quality gates for development process
Andrii Soldatenko6.5K vues
Building social network with Neo4j and Python par Andrii Soldatenko
Building social network with Neo4j and PythonBuilding social network with Neo4j and Python
Building social network with Neo4j and Python
Andrii Soldatenko7.8K vues

Similaire à Créer une base NoSQL en 1 heure

Server side JavaScript: going all the way par
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the wayOleg Podsechin
10K vues59 diapositives
CODE FOR echo_client.c A simple echo client using TCP #inc.pdf par
CODE FOR echo_client.c A simple echo client using TCP  #inc.pdfCODE FOR echo_client.c A simple echo client using TCP  #inc.pdf
CODE FOR echo_client.c A simple echo client using TCP #inc.pdfsecunderbadtirumalgi
5 vues7 diapositives
Extending functionality in nginx, with modules! par
Extending functionality in nginx, with modules!Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!Trygve Vea
10.5K vues61 diapositives
Remote Procedure Call par
Remote Procedure CallRemote Procedure Call
Remote Procedure CallNadia Nahar
587 vues9 diapositives
Socket programming par
Socket programming Socket programming
Socket programming Rajivarnan (Rajiv)
981 vues25 diapositives

Similaire à Créer une base NoSQL en 1 heure(20)

Server side JavaScript: going all the way par Oleg Podsechin
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
Oleg Podsechin10K vues
Extending functionality in nginx, with modules! par Trygve Vea
Extending functionality in nginx, with modules!Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!
Trygve Vea10.5K vues
Remote Procedure Call par Nadia Nahar
Remote Procedure CallRemote Procedure Call
Remote Procedure Call
Nadia Nahar587 vues
How to Leverage Go for Your Networking Needs par DigitalOcean
How to Leverage Go for Your Networking NeedsHow to Leverage Go for Your Networking Needs
How to Leverage Go for Your Networking Needs
DigitalOcean99 vues
Anchoring Trust: Rewriting DNS for the Semantic Network with Ruby and Rails par Eleanor McHugh
Anchoring Trust: Rewriting DNS for the Semantic Network with Ruby and RailsAnchoring Trust: Rewriting DNS for the Semantic Network with Ruby and Rails
Anchoring Trust: Rewriting DNS for the Semantic Network with Ruby and Rails
Eleanor McHugh1.6K vues
sbt-ethereum: a terminal for the world computer par Steve Waldman
sbt-ethereum: a terminal for the world computersbt-ethereum: a terminal for the world computer
sbt-ethereum: a terminal for the world computer
Steve Waldman52 vues
Session Server - Maintaing State between several Servers par Stephan Schmidt
Session Server - Maintaing State between several ServersSession Server - Maintaing State between several Servers
Session Server - Maintaing State between several Servers
Stephan Schmidt1.8K vues
Chatting dengan beberapa pc laptop par yayaria
Chatting dengan beberapa pc laptopChatting dengan beberapa pc laptop
Chatting dengan beberapa pc laptop
yayaria465 vues
Use perl creating web services with xml rpc par Johnny Pork
Use perl creating web services with xml rpcUse perl creating web services with xml rpc
Use perl creating web services with xml rpc
Johnny Pork977 vues
OpenSSL Basic Function Call Flow par William Lee
OpenSSL Basic Function Call FlowOpenSSL Basic Function Call Flow
OpenSSL Basic Function Call Flow
William Lee5.2K vues
NATS + Docker meetup talk Oct - 2016 par wallyqs
NATS + Docker meetup talk Oct - 2016NATS + Docker meetup talk Oct - 2016
NATS + Docker meetup talk Oct - 2016
wallyqs924 vues
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm par Apcera
Simple and Scalable Microservices: Using NATS with Docker Compose and SwarmSimple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Apcera4.9K vues

Plus de Amaury Bouchard

Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk) par
Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)
Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)Amaury Bouchard
7.4K vues12 diapositives
Démons en PHP, de inetd à ZeroMQ par
Démons en PHP, de inetd à ZeroMQDémons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQAmaury Bouchard
6.2K vues63 diapositives
Architectures réparties en environnement web par
Architectures réparties en environnement webArchitectures réparties en environnement web
Architectures réparties en environnement webAmaury Bouchard
2.1K vues37 diapositives
De geek à directeur technique - Conférence SupInfo 2010 par
De geek à directeur technique - Conférence SupInfo 2010De geek à directeur technique - Conférence SupInfo 2010
De geek à directeur technique - Conférence SupInfo 2010Amaury Bouchard
2.4K vues54 diapositives
De geek à directeur technique - Conférence Université de Montréal 2010 par
De geek à directeur technique - Conférence Université de Montréal 2010De geek à directeur technique - Conférence Université de Montréal 2010
De geek à directeur technique - Conférence Université de Montréal 2010Amaury Bouchard
1.1K vues54 diapositives
De geek à directeur technique - Conférence UQÀM 2010 par
De geek à directeur technique - Conférence UQÀM 2010De geek à directeur technique - Conférence UQÀM 2010
De geek à directeur technique - Conférence UQÀM 2010Amaury Bouchard
1.1K vues54 diapositives

Plus de Amaury Bouchard(7)

Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk) par Amaury Bouchard
Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)
Organisation personnelle : GTD et matrice d'Eisenhower (Lightning Talk)
Amaury Bouchard7.4K vues
Démons en PHP, de inetd à ZeroMQ par Amaury Bouchard
Démons en PHP, de inetd à ZeroMQDémons en PHP, de inetd à ZeroMQ
Démons en PHP, de inetd à ZeroMQ
Amaury Bouchard6.2K vues
Architectures réparties en environnement web par Amaury Bouchard
Architectures réparties en environnement webArchitectures réparties en environnement web
Architectures réparties en environnement web
Amaury Bouchard2.1K vues
De geek à directeur technique - Conférence SupInfo 2010 par Amaury Bouchard
De geek à directeur technique - Conférence SupInfo 2010De geek à directeur technique - Conférence SupInfo 2010
De geek à directeur technique - Conférence SupInfo 2010
Amaury Bouchard2.4K vues
De geek à directeur technique - Conférence Université de Montréal 2010 par Amaury Bouchard
De geek à directeur technique - Conférence Université de Montréal 2010De geek à directeur technique - Conférence Université de Montréal 2010
De geek à directeur technique - Conférence Université de Montréal 2010
Amaury Bouchard1.1K vues
De geek à directeur technique - Conférence UQÀM 2010 par Amaury Bouchard
De geek à directeur technique - Conférence UQÀM 2010De geek à directeur technique - Conférence UQÀM 2010
De geek à directeur technique - Conférence UQÀM 2010
Amaury Bouchard1.1K vues
De geek à directeur technique - Conférence Epitech 2010 par Amaury Bouchard
De geek à directeur technique - Conférence Epitech 2010De geek à directeur technique - Conférence Epitech 2010
De geek à directeur technique - Conférence Epitech 2010
Amaury Bouchard1.4K vues

Dernier

Ransomware is Knocking your Door_Final.pdf par
Ransomware is Knocking your Door_Final.pdfRansomware is Knocking your Door_Final.pdf
Ransomware is Knocking your Door_Final.pdfSecurity Bootcamp
59 vues46 diapositives
SUPPLIER SOURCING.pptx par
SUPPLIER SOURCING.pptxSUPPLIER SOURCING.pptx
SUPPLIER SOURCING.pptxangelicacueva6
16 vues1 diapositive
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ... par
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...Jasper Oosterveld
19 vues49 diapositives
MVP and prioritization.pdf par
MVP and prioritization.pdfMVP and prioritization.pdf
MVP and prioritization.pdfrahuldharwal141
31 vues8 diapositives
Info Session November 2023.pdf par
Info Session November 2023.pdfInfo Session November 2023.pdf
Info Session November 2023.pdfAleksandraKoprivica4
13 vues15 diapositives
PharoJS - Zürich Smalltalk Group Meetup November 2023 par
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023Noury Bouraqadi
132 vues17 diapositives

Dernier(20)

ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ... par Jasper Oosterveld
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...
ESPC 2023 - Protect and Govern your Sensitive Data with Microsoft Purview in ...
PharoJS - Zürich Smalltalk Group Meetup November 2023 par Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi132 vues
Unit 1_Lecture 2_Physical Design of IoT.pdf par StephenTec
Unit 1_Lecture 2_Physical Design of IoT.pdfUnit 1_Lecture 2_Physical Design of IoT.pdf
Unit 1_Lecture 2_Physical Design of IoT.pdf
StephenTec12 vues
Special_edition_innovator_2023.pdf par WillDavies22
Special_edition_innovator_2023.pdfSpecial_edition_innovator_2023.pdf
Special_edition_innovator_2023.pdf
WillDavies2218 vues
Case Study Copenhagen Energy and Business Central.pdf par Aitana
Case Study Copenhagen Energy and Business Central.pdfCase Study Copenhagen Energy and Business Central.pdf
Case Study Copenhagen Energy and Business Central.pdf
Aitana16 vues
Igniting Next Level Productivity with AI-Infused Data Integration Workflows par Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software280 vues
Voice Logger - Telephony Integration Solution at Aegis par Nirmal Sharma
Voice Logger - Telephony Integration Solution at AegisVoice Logger - Telephony Integration Solution at Aegis
Voice Logger - Telephony Integration Solution at Aegis
Nirmal Sharma39 vues
Serverless computing with Google Cloud (2023-24) par wesley chun
Serverless computing with Google Cloud (2023-24)Serverless computing with Google Cloud (2023-24)
Serverless computing with Google Cloud (2023-24)
wesley chun11 vues

Créer une base NoSQL en 1 heure

  • 1. Créer un serveur noSQL en une heure
  • 2. Bases noSQL Bibliothèques utilisées Présentation AngstromDB Étude de code Benchmark & évolutions Créer un serveur noSQL
  • 4. Aller plus loin Scalabilité horizontale Haute disponibilité Big Data S'affranchir Modèle relationnel Transactions ACID Principe général
  • 5. Types de bases noSQL Clé-valeur Document Colonne Graph Dynamo Riak Redis Voldemort Tokyo Tyrant MemcacheDB FoundationDB MongoDB CouchDB CouchBase HyperDex RethinkDB Cassandra Hadoop / Hbase Accumulo Neo4J Allegro Virtuoso InfoGrid
  • 7. Le successeur de ZeroMQ Bibliothèque réseau avec des super-pouvoirs Nanomsg
  • 8. Gestion de files de messages Protocole spécifique 14 langages supportés Redéfinition des concepts réseau Nanomsg
  • 9. Méthodes de transport Inter-threads inproc Inter-processus ipc Inter-machines tcp
  • 10. Découplage du sens de connexion ServeurClient
  • 11. Découplage du sens de connexion ServeurClient
  • 24. Stockage paires clé-valeur multivaluées Persistance sur disque, mapping RAM Transactionnel (1 thread d'écriture) Au cœur de OpenLDAP LMDB (LightningDB)
  • 27. Serveur paires clé-valeur Codé en C Basé sur des bibliothèques reconnues Protocole binaire Aucun contrôle d'erreur Implémentation naïve
  • 28. API très simple PUT Ajout ou mise-à-jour de clé GET Retourne une valeur DELETE Efface une clé
  • 29. Protocole : DELETE 2 cmd taille clé clé 1 1 1 à 255 octets Requête Réponse 1 statut 1
  • 30. Protocole : GET 3 cmd taille clé clé 1 1 1 à 255 octets Requête Réponse 1 statut taille données données 1 4 0 à 4 GO
  • 31. Protocole : PUT 1 cmd taille clé clé 1 1 1 à 255 octets Requête Réponse 1 statut taille données données 1 4 0 à 4 GO
  • 32. Multi-threadé Thread principal Attend les nouvelles connexions Threads de communication Un thread par client connecté Thread d'écriture Pas d'écriture concurrente
  • 33. Thread principal Threads de communication LMDB Thread d'écriture
  • 36. Démarrage /* * db Pointer to the database environment. * socket Socket descriptor for incoming connections. * threads_socket Nanomsg socket for threads communication. * writer_tid ID of the writer thread. * comm_threads Array of communication threads. */ typedef struct angstrom_s { MDB_env *db; int socket; int threads_socket; pthread_t writer_tid; struct comm_thread_s *comm_threads; } angstrom_t; /* * tid Thread's identifier. * angstrom Pointer to the server's structure. * client_sock Socket used to communicate with the client. * writer_sock Nanomsg socket to send data to the writer. */ typedef struct comm_thread_s { pthread_t tid; angstrom_t *angstrom; int client_sock; int writer_sock; } comm_thread_t; angstrom.h
  • 37. Démarrage int main() { angstrom_t *angstrom; int i; // server init angstrom = calloc(1, sizeof(angstrom_t)); angstrom->socket = angstrom->threads_socket = -1; angstrom->comm_threads = calloc(NBR_THREADS, sizeof(comm_thread_t)); // open the database angstrom->db = database_open(DEFAULT_DB_PATH, DEFAULT_MAPSIZE, NBR_THREADS); // create the nanomsg socket for threads communication angstrom->threads_socket = nn_socket(AF_SP, NN_PUSH); nn_bind(angstrom->threads_socket, ENDPOINT_THREADS_SOCKET); // create the writer thread pthread_create(&angstrom->writer_tid, NULL, thread_writer_loop, angstrom); main.c
  • 38. Démarrage int main() { angstrom_t *angstrom; int i; // server init angstrom = calloc(1, sizeof(angstrom_t)); angstrom->socket = angstrom->threads_socket = -1; angstrom->comm_threads = calloc(NBR_THREADS, sizeof(comm_thread_t)); // open the database angstrom->db = database_open(DEFAULT_DB_PATH, DEFAULT_MAPSIZE, NBR_THREADS); // create the nanomsg socket for threads communication angstrom->threads_socket = nn_socket(AF_SP, NN_PUSH); nn_bind(angstrom->threads_socket, ENDPOINT_THREADS_SOCKET); // create the writer thread pthread_create(&angstrom->writer_tid, NULL, thread_writer_loop, angstrom); main.c "inproc://threads_socket"
  • 39. Démarrage // create communication threads for (i = 0; i < NBR_THREADS; i++) { comm_thread_t *thread = &(angstrom->comm_threads[i]); thread->client_sock = -1; thread->angstrom = angstrom; pthread_create(&thread->tid, 0, thread_comm_loop, thread); pthread_detach(thread->tid); } // create listening socket angstrom->socket = _create_listening_socket(DEFAULT_PORT); // server loop _main_thread_loop(angstrom); return (0); } main.c
  • 40. Démarrage MDB_env *database_open(const char *path, size_t mapsize, unsigned int nbr_threads) { MDB_env *env = NULL; mdb_env_create(&env); mdb_env_set_mapsize(env, mapsize); mdb_env_set_maxreaders(env, nbr_threads); mdb_env_open(env, path, 0, 0664); return (env); } database.c
  • 41. Démarrage static int _create_listening_socket(unsigned short port) { int sock; struct sockaddr_in addr; unsigned int addr_size; const int on = 1; // create the socket sock = socket(AF_INET, SOCK_STREAM, 0); // some options setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)); setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)); // binding to any interface addr_size = sizeof(addr); bzero(&addr, addr_size); addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = AF_INET; addr.sin_port = htons(port); bind(sock, (struct sockaddr*)&addr, addr_size); listen(sock, SOMAXCONN); return (sock); } main.c
  • 42. Nouvelle connexion static void _main_thread_loop(angstrom_t *angstrom) { int fd; struct sockaddr_in addr; unsigned int addr_size; const int on = 1; addr_size = sizeof(addr); for (; ; ) { bzero(&addr, addr_size); // accept a new connection if ((fd = accept(angstrom->socket, (struct sockaddr*)&addr, &addr_size)) < 0) { continue ; } setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)); // send the file descriptor number to comm threads nn_send(angstrom->threads_socket, &fd, sizeof(fd), 0); } } main.c
  • 43. Nouvelle connexion void *thread_comm_loop(void *param) { comm_thread_t *thread = param; int in_sock; // opening a connection to the writer thread thread->writer_sock = nn_socket(AF_SP, NN_PUSH); nn_connect(thread->writer_sock, ENDPOINT_WRITER_SOCKET); // opening a connection to the main thread in_sock = nn_socket(AF_SP, NN_PULL); nn_connect(in_sock, ENDPOINT_THREADS_SOCKET); // loop to process new connections for (; ; ) { // waiting for a new connection to handle nn_recv(in_sock, &thread->client_sock, sizeof(int), 0); // process connection _process_connection(thread); } return (NULL); } thread_com munication.c
  • 44. Nouvelle connexion void *thread_comm_loop(void *param) { comm_thread_t *thread = param; int in_sock; // opening a connection to the writer thread thread->writer_sock = nn_socket(AF_SP, NN_PUSH); nn_connect(thread->writer_sock, ENDPOINT_WRITER_SOCKET); // opening a connection to the main thread in_sock = nn_socket(AF_SP, NN_PULL); nn_connect(in_sock, ENDPOINT_THREADS_SOCKET); // loop to process new connections for (; ; ) { // waiting for a new connection to handle nn_recv(in_sock, &thread->client_sock, sizeof(int), 0); // process connection _process_connection(thread); } return (NULL); } thread_com munication.c "inproc://writer_socket" "inproc://threads_socket"
  • 45. Nouvelle connexion static void _process_connection(comm_thread_t *thread) { uint8_t cmd; // loop on incoming requests for (; ; ) { // read command byte if (read(thread->client_sock, &cmd, sizeof(cmd)) <= 0) { close(thread->client_sock); break; } // interpret command switch (cmd) { case PROTO_PUT: command_put(thread); break; case PROTO_DELETE: command_del(thread); break; case PROTO_GET: command_get(thread); break; } } } thread_com munication.c
  • 46. Lecture de données void command_get(comm_thread_t *thread) { uint8_t key_size, response = PROTO_OK; uint32_t value_size; MDB_val key, value; // read key length read(thread->client_sock, &key_size, sizeof(key_size)); // read key data key.mv_data = malloc(key_size); read(thread->client_sock, key.mv_data, key_size); // get data key.mv_size = (size_t)key_size; database_get(thread->angstrom->db, &key, &value); // send response to the client write(thread->client_sock, &response, sizeof(response)); value_size = htonl((uint32_t)value.mv_size); write(thread->client_sock, &value_size, sizeof(value_size)); if (value_size) write(thread->client_sock, value.mv_data, value.mv_size); } command_ get.c
  • 47. Lecture de données void database_get(MDB_env *db, MDB_val *key, MDB_val *value) { MDB_dbi dbi; MDB_txn *txn; // transaction init mdb_txn_begin(db, NULL, MDB_RDONLY, &txn); // open database in read-write mode mdb_dbi_open(txn, NULL, 0, &dbi); // get data if (mdb_get(txn, dbi, key, value)) bzero(value, sizeof(*value)); // end of transaction mdb_txn_abort(txn); // close database mdb_dbi_close(db, dbi); } database.c
  • 48. Thread d'écriture /* * type Type of action (WRITE_PUT, WRITE_DEL). * key Size and content of the key. * value Size and content of the value. */ typedef struct writer_msg_s { enum { WRITE_PUT, WRITE_DEL } type; MDB_val key; MDB_val value; } writer_msg_t; angstrom.h
  • 49. Thread d'écriture void *thread_writer_loop(void *param) { angstrom_t *angstrom = param; int socket; // create the nanomsg socket for threads communication socket = nn_socket(AF_SP, NN_PULL); nn_bind(socket, ENDPOINT_WRITER_SOCKET); // loop to process new connections for (; ; ) { writer_msg_t *msg; // waiting for a new connection to handle if (nn_recv(socket, &msg, sizeof(writer_msg_t*), 0) < 0) continue; // processing switch (msg->type) { case WRITE_PUT: database_put(angstrom->db, &msg->key, &msg->value); break; case WRITE_DEL: database_del(angstrom->db, &msg->key); break; } thread_ writer.c
  • 50. Thread d'écriture void *thread_writer_loop(void *param) { angstrom_t *angstrom = param; int socket; // create the nanomsg socket for threads communication socket = nn_socket(AF_SP, NN_PULL); nn_bind(socket, ENDPOINT_WRITER_SOCKET); // loop to process new connections for (; ; ) { writer_msg_t *msg; // waiting for a new connection to handle if (nn_recv(socket, &msg, sizeof(writer_msg_t*), 0) < 0) continue; // processing switch (msg->type) { case WRITE_PUT: database_put(angstrom->db, &msg->key, &msg->value); break; case WRITE_DEL: database_del(angstrom->db, &msg->key); break; } thread_ writer.c "inproc://writer_socket"
  • 51. Thread d'écriture // free data if (msg->key.mv_data) free(msg->key.mv_data); if (msg->value.mv_data) free(msg->value.mv_data); free(msg); } return (NULL); } thread_ writer.c
  • 52. Effacement de clé void command_delete(comm_thread_t *thread) { uint8_t key_size, response = PROTO_OK; void *key; writer_msg_t *msg; // read key length read(thread->client_sock, &key_size, sizeof(key_size)); // read key data key = malloc(key_size); read(thread->client_sock, key, key_size); // create message msg = calloc(1, sizeof(writer_msg_t)); msg->type = WRITE_DEL; msg->key.mv_size = (size_t)key_size; msg->key.mv_data = key; // send the message to the writer thread nn_send(thread->writer_sock, &msg, sizeof(msg), 0); // send response to the client write(thread->client_sock, &response, sizeof(response)); } command_ delete.c
  • 53. Effacement de clé void database_del(MDB_env *db, MDB_val *key) { MDB_dbi dbi; MDB_txn *txn; // transaction init mdb_txn_begin(db, NULL, 0, &txn); // open database in read-write mode mdb_dbi_open(txn, NULL, 0, &dbi); // delete key mdb_del(txn, dbi, key, NULL); // close database mdb_dbi_close(db, dbi); // transaction commit mdb_txn_commit(txn); } database.c
  • 54. Ajout / mise-à-jour de clé void command_put(comm_thread_t *thread) { uint8_t key_size, response = PROTO_OK; void *key, *value = NULL; uint32_t value_size; writer_msg_t *msg; // read key length read(thread->client_sock, &key_size, sizeof(key_size)); // read key data key = malloc(key_size); read(thread->client_sock, key, key_size); // read value length read(thread->client_sock, &value_size, sizeof(value_size)); value_size = ntohl(value_size); if (value_size > 0) { // read value data value = malloc(value_size); read(thread->client_sock, value, value_size); } command_ put.c
  • 55. Ajout / mise-à-jour de clé // create message msg = malloc(sizeof(writer_msg_t)); msg->type = WRITE_PUT; msg->key.mv_size = (size_t)key_size; msg->key.mv_data = key; msg->value.mv_size = (size_t)value_size; msg->value.mv_data = value; // send the message to the writer thread nn_send(thread->writer_sock, &msg, sizeof(msg), 0); // send response to the client write(thread->client_sock, &response, sizeof(response)); } command_ put.c
  • 56. Ajout / mise-à-jour de clé void database_put(MDB_env *db, MDB_val *key, MDB_val *value) { MDB_dbi dbi; MDB_txn *txn; // transaction init mdb_txn_begin(db, NULL, 0, &txn); // open database in read-write mode mdb_dbi_open(txn, NULL, 0, &dbi); // put data mdb_put(txn, dbi, key, value, 0); // close database mdb_dbi_close(db, dbi); // transaction commit mdb_txn_commit(txn); } database.c
  • 58. cloc Language files comment code ------------------------------------------------- C 7 132 212 C Header 1 111 55 make 1 13 27 ------------------------------------------------- SUM: 9 256 294 sloccount Schedule Estimate, Years (Months) = 0.17 (2.06) Total Estimated Cost to Develop = $ 6,753
  • 59. Benchmark Base Écritures Lectures AngstromDB 22 ms 55 ms Couchbase 25 ms 22 ms Redis 29 ms 30 ms MongoDB 39 ms 27 ms 45 écritures / lectures séquentielles de données représentatives
  • 61. Réduire les appels systèmes ! Bufferiser les lectures réseau Regrouper les écritures réseau Facile à tester (sendmsg vs write) Pour commencer
  • 62. Benchmark Base Écritures Lectures AngstromDB 22 ms 55 ms AngstromDB 22 ms 26 ms Couchbase 25 ms 22 ms Redis 29 ms 30 ms MongoDB 39 ms 27 ms
  • 63. Compression à la volée (Zippy) Sérialisation de données (MsgPack) Transactions en lecture … Mono-processus asynchrone ? Pour aller plus loin