A Few things happened on the way to LMDB Presented by Andrew Bartlet Samba Team - Catalyst / / June 2018 Samba is a member project of the Sofuware Freedom Conseraancy
Andrew Bartlet and Catalyst’s Samba Team Samba Deaeloper since 2001 Garming Sam – ● Based in Wellington, New Zealand Douglas Bagnall – ● Team lead for the Catalyst Samba Team, Gary Lockyer ● – including: Tim Beale – Joe Guo – Aarron Haslet – Jamie McClymont –
Not really a story about LMDB LMDB prety much did what it said on the tn ● Instead LMDB taught us about Samba and LDB ● Numerous locking issues found and fied ● A new key-aalue layer added ● And so, so many tests ●
Customer request: 64-bit DB Concerned that the 4GB DB could be flled too quickly ● Wantng to store g 100,000 users in a single domainn – Main concern is the hard limit of TDB ● LMDB chosen as a modern key-aalue store ● Used in OpenLDAP –
Timeline LMDB was prototyped in Jan 2017 ● Garming Sam – Inspired by, but rewriten from Jakob Hrozek’s earlier prototype – GUID-indei LDB implemented in July/August 2017 ● LMDB requires a maiimum 511 byte key length – Primary deaelopment Jan → May 2018 ● Gary Lockyer –
A new approach: Key/Value layer Jakob’s approach was to copy ldb_tdb and modify it ● Garming and I decided to instead add a key-aalue layer ● Aaoid code duplicaton – Allow more than just LMDB (perhaps LMDBi, LeaelDB) – Share performance and correctness improaements with ldb_tdb – Like dbwrap in concept but specifc to LDB needs –
Key-value API int (* store )(struct ltdb_priaate *ltdb, struct ldb_aal key, struct ldb_aal data, int fags) ● int (* delete )(struct ltdb_priaate *ltdb, struct ldb_aal key); ● int (* iterate )(struct ltdb_priaate *ltdb, ldb_ka_traaerse_fn fn, aoid *cti); ● int (* update_in_iterate )(struct ltdb_priaate *ltdb, struct ldb_aal key, struct ldb_aal key2, ● struct ldb_aal data, aoid *cti); int (* fetch_and_parse )(struct ltdb_priaate *ltdb, struct ldb_aal key, int (*parser)(struct ● ldb_aal key, struct ldb_aal data, aoid *priaate_data), aoid *cti);
Locking API Read Locks Transactons ● ● int (* lock_read )(struct ldb_module *); int (* begin_write )(struct ltdb_priaate *); – – int (* unlock_read )(struct ldb_module *); int (* prepare_write )(struct ltdb_priaate *); – – int (* abort_write )(struct ltdb_priaate *); – int (* fjnish_write )(struct ltdb_priaate *); –
Meta API int (* error )(struct ltdb_priaate *ltdb); ● const char * (* errorstr )(struct ltdb_priaate *ltdb); ● const char * (* name )(struct ltdb_priaate *ltdb); ● bool (* has_changed )(struct ltdb_priaate *ltdb); ● bool (* transacton_actve )(struct ltdb_priaate *ltdb); ●
First Hurdle: Locking Eaen the prototype found issuesn ● Demonstrated the lack of whole-DB locking – Fiied for Samba 4.7 last year – Probably behind many of our replicaton issues ●
Second Hurdle: More Locking! It just wouldn’t pass make testn ● More strange failures in replicaton – Unlock ordering issues in replicaton ● highestCommitedUSN aisible before the data – Fiies proposed for backport to Samba 4.7 and 4.8 – Modifcaton without locks (at startup) in Samba 4.8 ● DB-init tme only, but not good – Added checks to key-aalue layer to preaent re-occurrence –
Third hurdle: Maximum key size TDB has an unlimited key size ● LMDB is limited to 511 bytes ● LDB traditonally used the DN as the key ● Addressed by the new GUID key system –
But what about indexes? Indei created by putng indei key and aalue in the TDB key ● @INDEX:SAMACCOUNTNAME:abartlet – Original plan was to keep the indei in TDB ● But the more we understood the locking the less we wanted to mii TDB and LMDB – lock ordering Addressed by truncatng the indei and coping with multple matches ● Ironically found and fied the 4.8 upgrade bug – But didn’t realise the importance before eaeryone notced –
And what about performance? Three performance tools measured so far: ● Make perfuest on our Hardware test seraer – Old AMD Athalonn ● Trafc replay tool in the cloud – Adding users and users into groups of my workstaton –
Make perfest: a small dissapointment 30% performance lossn ● LMDB uses write(), and a read-only mmap() – socket_wrapper intercepts write() – Workaround: ● Use Linui userspace namespaces instead of socket_wrapper – Patches to upstream this stll pending – End result is no major change, perhaps 10% slower ●
Trafc replay This is a tool to replay an amplifed anonymous trafc capture ● Similar numbers to TDB ● Need to re-try with a larger DB ● We think LMDB will show most strength at large sizes –
Adding users and users into groups of my workstaton In a four-hour benchmark adding users and adding to one to four groups (in rotaton): ● Samba 4.4: 26,000 users – Samba 4.5: 48,000 users – Samba 4.6: 55,000 users – Samba 4.7: 85,000 users – Samba 4.8: 100,000 users – Samba 4.9: 100,000 users (TDB) – Samba 4.9: 45,000 users (LMDB) –
Ouch. What went wrong! fsync()/fdatasync()/msync() stll called ● Patches quickly writen ● New numbers: ● Samba 4.9: 100,000 users (TDB) – Samba 4.9: 124,000 users (LMDB, no fsync()) – Lesson: ● Samba’s module stack is stll the slowest factor –
TDB vs LMDB (latency vs number of users added)
Flame Graph Search lt.. lt.. lm.. lm.. lt.. lt.. lt.. lt.. lt.. lt.. ltdb_se.. ltdb_s.. ltdb_se.. ltdb_s.. ltdb_ca.. ltdb_c.. tevent_.. tevent.. epoll_e.. epoll_.. std_eve.. std_ev.. _tevent.. _teven.. __.. ldb_wait ldb_wait ltdb.. dsdb_mo.. dsdb_m.. lmdb.. replmd_m.. replmd_.. ltdb.. replmd_modify ltdb.. ldb_next_request ltdb.. rdn_name_modify ltdb.. ldb_next_request ltdb.. attr_handler teve.. objectclass_attrs.. epol.. ldb_next_request std_.. instancetype_mod _tev.. ldb_next_request ldb_.. password_hash_nee.. dsdb.. password_hash_mod.. dsdb.. ldb_next_request saml.. samldb_modify ldb_next_request acl_modify _t.. ldb_next_request _tc.. descriptor_modify _tc.. ldb_next_request _tc.. tombstone_reanimate_modify _tc_f.. ldb_next_request _tc_fre.. objectclass_modify _tc_fre.. ldb_next_request _tc_fre.. log_modify _tc_fre.. ldb_next_request _tc_fre.. extended_dn_in_fjx _tc_fre.. extended_dn_in_modify _.. _tc_fre.. ldb_next_request _t.. _tc_fre.. extended_replace_callback _t.. lt.. _tc_fre.. ldb_module_done _tc.. lt.. _tc_fre.. es_callback _tal.. __.. d.. ldb_dn_fr.. td.. _tc_fre.. ldb_module_done _tal.. d.. dsdb_dn_parse_trusted td.. _tc_fre.. operational_callback extended_callback lt.. _tc_fre.. ldb_module_done extended_callback_ldb lt.. lt.. _tc_fre.. __m.. extended_callback ldb_module_send_entry ld.. lt.. _tc_fre.. ltdb_.. extended_callback_ldb dsdb_next_callback lt.. pa.. lt.. _tc_fre.. lmdb_.. p.. ldb_module_done ldb_module_send_entry lm.. ld.. lt.. _tc_fre.. ltdb_.. __me.. dsdb_next_callback partition_req_callback lt.. li.. ltd.. _tc_fre.. ltdb_.. ltdb_.. ldb_module_done ldb_module_send_entry lt.. lt.. ld.. ltd.. _tc_fre.. ltdb_modify_i.. partition_req_callback ltdb_search_and_return_base re.. ltd.. _tc_fre.. ltdb_modify ltdb_request_done ltdb_search ld.. ltdb_.. _tc_fre.. ltdb_callback ge.. de.. teven.. _tc_fre.. tevent_common_loop_timer_delay __.. ld.. epoll.. _tc_fre.. epoll_event_loop_once ext.. lo.. std_e.. _tc_fre.. std_event_loop_once new.. ld.. _teve.. _talloc.. _tevent_loop_once h.. vfs.. un.. ld.. ldb_w.. _talloc.. ldb_wait d.. _.. sys.. do.. py_ldb_add py_ldb_modify d.. s.. do_.. sy .. PyEval_EvalFrameEx e.. pag.. ent.. do.. [unknown] _.. __memmo.. __p.. _int_f.. en.. [unknown] __GI.. __.. _int_mal.. python
OK, so not so bad We addressed the customer’s desire for scale ● Currently limited to 6GB but that is compile-tme constant only – Opens up new opportunites ● Current Status: ● Stll accessed behind sam.ldb (a TDB) – Stll one-subtree per DB fle –
LMDB: The future Use the LMDB b-tree propertes in for the indei ● Allow prefi matching – Allow <= etc – Use sub-databases: ● Perhaps one per indei? – Perhaps one per sub-tree? – Use nested transactons to make the indei safer ●
LMDB: Sharp Edges Difgerent locking behaaiour (no eiclusiae access) ● Files are sparse by default ● DB operatons can fll the fle and partton without going aia a specifc resize – Files are not eitended automatcally ● The inaerse to the aboae, when a fle is full unlike TDB there is no auto-resize – Requires that the admin or Samba know the size up-front – LDB / Samba has not required this kind of planning in the past ● Need real-world eiperience ●
Beyond LMDB: Supportng more connectons on each DC Samba 4.6 remoaes single-process restrictons on NETLOGON ● Really important for 802.1i backed authentcaton – Samba 4.7 supports a mult-process LDAP seraer ● Actually reduces number of connectons you can ft in memory (oops) – Samba 4.8 adds a prefork mode for LDAP ● Great for a big AD DC with many, many clients – Samba 4.9: should we make prefork the default? ● Howeaer NETLOGON would be single-process in that mode (ouch) –
Recommend
More recommend