OpenLDAP-LMDB (Lightning Memory-Mapped Database) ou LMDB est une base de données embarquée transactionnelle de stockage clé-valeur qui est disponible sous Linux. En 2009, le projet OpenLDAP est préoccupé par l’avenir de Berkeley DB, passé dans le giron d’Oracle. Le projet OpenLDAP a finalement décidé de faire un fork de Berkeley DB, appelée MDB. Cette librairie devient LMDB et est utilisée massivement sous Linux.
Portage sous Windows
Avant de pouvoir l’utiliser sous forme de DLL Windows, il est impératif de migrer le code Linux vers Windows. La librairie contient du code pour Windows mais le portage reste incomplet car l’utilisation des noms de fichiers contient un / au lieu de \\ et cela ne marche que sous Linux, une fois cette modification effectuée, Il faut donc exporter les diverses fonctions pour obtenir une DLL.
LMDBWindowsDll
Le portage de la DLL sous Windows est disponible sur : https://github.com/ChristophePichaud/LMDBWindows/LMDBWindowsDll
En Debug, la DLL LMDBWindowsDllD64.dll fait 235 KB. En Release, elle en fait moins de 100 KB, ce qui est très léger.
Utilisation de LMDB API
L’API est du C pur et dur: il y a des structures à définir et des structures à utiliser. Les fonctions sont préfixées par mdb_, Bien que l’utilisation du C soit basic, elle peut rebuter certaines personnes. Il faut passer des buffers, des longueurs, autrement dit du C. Il est également préférable d’encapsuler l’API C en C++ et mettre à disposition des std::string.
Cette version d’API est beaucoup plus simple à utiliser: il faut déclarer un objet, faire appel à Init en y passant le nom de la base de données, et ensuite faire Get/Set comme on le souhaite.
Comme on le voit ci-dessus, l’ajout de données se fait par clé et valeur.
La base de données
Elle est constituée de deux fichiers :
- data.mdb
- lock.mdb
La méthode Init créé un répertoire du nom de la base dans c:\temp pour y stocker ces deux fichiers.
L’ouverture de la base
Comme vu précedemment, Init créé un répertoire, mais pas uniquement :
Init ouvre également une connexion à la base via mdb_dbi_open et positionne certains paramètres.
Gestion de la transaction
La transaction est créée via mdb_txn_begin et mdb_txn_commit :
Insertion de données
La création des données se fait via un appel à mdb_put :
Récupération de données
La récupération des données se fait via un appel à mdb_get ;
Evaluation des performances
Reprenons notre exemple et ajoutons des indicateurs de temps :
Le programme est simple. Il prend un nombre d’opérations à réaliser et ensuite il fait autant de GET et autant de SET sur un jeu de clé / valeur simple. Testons ce petit programme :
Opération | Nombre | Durée (ms) |
get | 1 | 0 |
set | 1 | 0 |
get | 10 | 0 |
set | 10 | 0 |
get | 100 | 15 |
set | 100 | 0 |
get | 1000 | 63 |
set | 1000 | 15 |
get | 10000 | 109 |
set | 10000 | 63 |
get | 100000 | 1141 |
set | 100000 | 640 |
Modifions maintenant le programme pour insérer et récupérer des documents jSON :
Voici le résultat :
Opération | Nombre | Durée (ms) |
get jSON | 1 | 0 |
set jSON | 1 | 0 |
get jSON | 10 | 0 |
set jSON | 10 | 0 |
get jSON | 100 | 0 |
set jSON | 100 | 0 |
get jSON | 1000 | 16 |
set jSON | 1000 | 16 |
get jSON | 10000 | 218 |
set jSON | 10000 | 63 |
get jSON | 100000 | 2375 |
set jSON | 100000 | 672 |
Les performances sont exceptionnelles et la taille de la base de données est conséquente (53 MB) :
Application pratique
Vous souhaitez utiliser une base de données de cache dans votre site web sur Azure mais vous hésitez entre DocumentDB ou MongoDB. Vous pouvez essayer LMDB, c’est une base gratuite et rapide. De plus LMDB possède aussi des fonctionnalités de curseur pour lire le contenu de la base.
Explorer la base
Voici le code qui permet de parcourir les données :
Le code de GetAllData() n’est pas compliqué, on déclare un curseur et on itère sur la méthode GetFromCursor. Voici le programme client :
CLMDBWrapperEx wr1;
wr1.Init(db);
wr1.GetAllData();
Voici la sortie console, on y remarque les documents jSON :
Si on modifie le programme client pour avoir des indications de temps :
Elasped Time for GetAllData: 32 ms
Il faut moins de 100ms pour charger 200.000 items soit 53 MB de data en RAM.
C’est du C/C++ ! C’est extrêmement performant.
Interop en C# .NET
Il existe des bindings pour le langage C#. C’est le rôle de LMDB.NET. Un portage C# qui fait des appels Interop à la DLL qui correspond. Voici le diagramme de classes simplifié :
Voici comment ouvrir une base :
Voici le code de récupération des informations jSON via le cursor :
Que vous souhaitiez utiliser SQLite ou un fichier de config, une base Azure comme Document DB ou MongoDB, il est important de prendre en compte cette nouvelle librairie qu’est LMDB. C’est gratuit, rapide et facile à mettre en œuvre. Elle explose les performances de toutes les bases NoSQL. Vous pouvez l’utiliser dans un container Docker avec la mise à disposition des données soit volatiles dans le container, soit persistentes dans des volumes partagés. LMDB et LMDB.NET, c’est le meilleur des deux mondes, le C++ pour la rapidité et le C# pour la facilité d’utilisation. Lancez-vous !
L’expertise Devoteam Modern Applications
Devoteam Modern Applications est spécialiste dans le développement et l’utilisation des technologies Microsoft .NET.
Avec LMDB, nous sommes capable d’apporter a nos clients un cache NoSQL pour des applications ASP.NET MVC. Par exemple on peut leur permettre de stocker des milliers d’informations en provenance de la base de données SQL Server et de les servir a leur client rapidement. C’est aussi une vitrine technologique pour permettre la mise en œuvre des containers sur Azure.
LMDB permet de concurrencer des produits comme MongoDB, Document DB et Azure Cosmos DB… en terme de prix et de performances. DMA réalise aussi des migrations applications traditionnelles en Microsoft .NET, .NET Core et sous Azure.
Découvrez notre playground Distributed Cloud