- 浏览: 254244 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
satan_1st:
据说可以用(*this)取得当前的lambda。
Recursive Lambda in C++ -
febird:
微软不死, 天理难容
再抱怨一下Windows7 -
sunzixun:
很有见解ace也可以精简的,我们就用阉割版的
asio/ACE/apr/libevent -
febird:
hamo2008 写道用win7以来基本上没有遇到这种情况了我 ...
造 windows 的微软很脑残 -
hamo2008:
用win7以来基本上没有遇到这种情况了
造 windows 的微软很脑残
项目地址:http://code.google.com/p/febird
使用前面介绍的序列化框架,可以非常简单地将Bekeley DB作为存储层,实现一个易于使用的,强类型的,持久化的map。
这个设计的的基本原则就是:模板作为一个薄的、类型安全的包装层,实现层的代码可以多个模板实例来公用,这样不但加快了编译时间,也减小了生成的代码尺寸。
这个实现相当于std::map<Key,Data>,但接口上也不完全相同,主要是基于易实现和性能考虑。
下一篇介绍std::map<Key1,std::map<Key2,Data> >的BerkeleyDB实现。
多的不说,贴上代码。
file: dbmap.h
- /* vim: set tabstop=4 : */
- #ifndef __febird_bdb_dbmap_h__
- #define __febird_bdb_dbmap_h__
- #if defined(_MSC_VER) && (_MSC_VER >= 1020)
- # pragma once
- #endif
- #include <db_cxx.h>
- #include "native_compare.h"
- #include "../io/DataIO.h"
- #include "../io/MemStream.h"
- #include "../refcount.h"
- namespace febird {
- class FEBIRD_DLL_EXPORT dbmap_iterator_impl_base : public RefCounter
- {
- public:
- class dbmap_base* m_owner;
- DBC* m_curp;
- int m_ret;
- public:
- dbmap_iterator_impl_base(class dbmap_base* owner);
- void init(DB* dbp, DB_TXN* txn, const char* func);
- virtual ~dbmap_iterator_impl_base();
- virtual void load_key(void* data, size_t size) = 0;
- virtual void load_val(void* data, size_t size) = 0;
- virtual void save_key(PortableDataOutput<AutoGrownMemIO>& oKey) = 0;
- void advance(u_int32_t direction_flag, const char* func);
- void update(const void* d, const char* func);
- void remove(const char* func);
- };
- class FEBIRD_DLL_EXPORT dbmap_base
- {
- DECLARE_NONE_COPYABLE_CLASS(dbmap_base)
- public:
- DB* m_db;
- size_t m_bulkSize;
- bt_compare_fcn_type m_bt_comp;
- dbmap_base(DB_ENV* env, const char* dbname
- , DB_TXN* txn
- , bt_compare_fcn_type bt_comp
- , const char* func
- );
- virtual ~dbmap_base();
- virtual void save_key(PortableDataOutput<AutoGrownMemIO>& dio, const void* key) const = 0;
- virtual void save_val(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const = 0;
- virtual dbmap_iterator_impl_base* make_iter() = 0;
- dbmap_iterator_impl_base* begin_impl(DB_TXN* txn, const char* func);
- dbmap_iterator_impl_base* end_impl(DB_TXN* txn, const char* func);
- dbmap_iterator_impl_base* find_impl(const void* k, DB_TXN* txn, u_int32_t flags, const char* func);
- bool insert_impl(const void* k, const void* d, u_int32_t flags, DB_TXN* txn, const char* func);
- bool remove_impl(const void* k, DB_TXN* txn, const char* func);
- void clear_impl(DB_TXN* txn, const char* func);
- };
- template<class Key, class Val, class Value, class Impl>
- class dbmap_iterator :
- public std::iterator<std::bidirectional_iterator_tag, Value, ptrdiff_t, const Value*, const Value&>
- {
- boost::intrusive_ptr<Impl> m_impl;
- void copy_on_write()
- {
- if (m_impl->getRefCount() > 1)
- {
- Impl* p = new Impl(m_impl->m_owner);
- m_impl->m_ret = m_impl->m_curp->dup(m_impl->m_curp, &p->m_curp, DB_POSITION);
- FEBIRD_RT_assert(0 == m_impl->m_ret, std::runtime_error);
- m_impl.reset(p);
- }
- }
- private:
- #ifdef _MSC_VER
- //# pragma warning(disable: 4661) // declaration but not definition
- //! MSVC will warning C4661 "declaration but not definition"
- void operator++(int) { assert(0); }
- void operator--(int) { assert(0); }
- #else
- //! disable, because clone iterator will cause very much time and resource
- void operator++(int);// { assert(0); }
- void operator--(int);// { assert(0); }
- #endif
- public:
- dbmap_iterator() {}
- explicit dbmap_iterator(dbmap_iterator_impl_base* impl)
- : m_impl(static_cast<Impl*>(impl))
- {
- assert(impl);
- assert(dynamic_cast<Impl*>(impl));
- }
- // bool exist() const { return DB_NOTFOUND != m_impl->m_ret && DB_KEYEMPTY != m_impl->m_ret; }
- bool exist() const { return 0 == m_impl->m_ret; }
- void update(const Val& val) { m_impl->update(&val, BOOST_CURRENT_FUNCTION); }
- void remove() { m_impl->remove(BOOST_CURRENT_FUNCTION); }
- dbmap_iterator& operator++()
- {
- assert(0 == m_impl->m_ret);
- copy_on_write();
- m_impl->advance(DB_NEXT, BOOST_CURRENT_FUNCTION);
- return *this;
- }
- dbmap_iterator& operator--()
- {
- assert(0 == m_impl->m_ret);
- copy_on_write();
- m_impl->advance(DB_PREV, BOOST_CURRENT_FUNCTION);
- return *this;
- }
- const Value& operator*() const
- {
- assert(0 == m_impl->m_ret);
- return m_impl->m_val;
- }
- const Value* operator->() const
- {
- assert(0 == m_impl->m_ret);
- return &m_impl->m_val;
- }
- Value& get_mutable() const
- {
- assert(0 == m_impl->m_ret);
- return m_impl->m_val;
- }
- };
- template<class Key, class Val>
- class dbmap : protected dbmap_base
- {
- DECLARE_NONE_COPYABLE_CLASS(dbmap)
- public:
- typedef Key key_type;
- typedef std::pair<Key, Val> value_type;
- protected:
- class dbmap_iterator_impl : public dbmap_iterator_impl_base
- {
- public:
- value_type m_val;
- dbmap_iterator_impl(dbmap_base* owner)
- : dbmap_iterator_impl_base(owner)
- {}
- virtual void load_key(void* data, size_t size)
- {
- PortableDataInput<MemIO> iKey;
- iKey.set(data, size);
- iKey >> m_val.first;
- FEBIRD_RT_assert(iKey.eof(), std::logic_error);
- }
- virtual void load_val(void* data, size_t size)
- {
- PortableDataInput<MinMemIO> iVal;
- iVal.set(data);
- iVal >> m_val.second;
- FEBIRD_RT_assert(iVal.diff(data) == size, std::logic_error);
- }
- virtual void save_key(PortableDataOutput<AutoGrownMemIO>& oKey1)
- {
- oKey1 << m_val.first;
- }
- };
- //! overrides
- void save_key(PortableDataOutput<AutoGrownMemIO>& dio, const void* key) const { dio << *(const Key*)key; }
- void save_val(PortableDataOutput<AutoGrownMemIO>& dio, const void* val) const { dio << *(const Val*)val; }
- dbmap_iterator_impl_base* make_iter() { return new dbmap_iterator_impl(this); }
- public:
- typedef dbmap_iterator<Key, Val, value_type, dbmap_iterator_impl>
- iterator, const_iterator;
- dbmap(DB_ENV* env, const char* dbname
- , DB_TXN* txn = NULL
- , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((Key*)(0))
- )
- : dbmap_base(env, dbname, txn, bt_comp, BOOST_CURRENT_FUNCTION)
- {
- }
- dbmap(DbEnv* env, const char* dbname
- , DbTxn* txn = NULL
- , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((Key*)(0))
- )
- : dbmap_base(env->get_DB_ENV(), dbname, txn ? txn->get_DB_TXN() : NULL, bt_comp, BOOST_CURRENT_FUNCTION)
- {
- }
- iterator begin(DB_TXN* txn = NULL) { return iterator(begin_impl(txn, BOOST_CURRENT_FUNCTION)); }
- iterator end (DB_TXN* txn = NULL) { return iterator(end_impl (txn, BOOST_CURRENT_FUNCTION)); }
- iterator begin(DbTxn* txn) { return iterator(begin_impl(txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION)); }
- iterator end (DbTxn* txn) { return iterator(end_impl (txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION)); }
- value_type back()
- {
- iterator iter = this->end();
- --iter;
- if (iter.exist())
- return *iter;
- throw std::runtime_error(BOOST_CURRENT_FUNCTION);
- }
- value_type front()
- {
- iterator iter = this->begin();
- if (iter.exist())
- return *iter;
- throw std::runtime_error(BOOST_CURRENT_FUNCTION);
- }
- iterator find(const Key& k, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k, txn, DB_SET, BOOST_CURRENT_FUNCTION));
- }
- iterator find(const Key& k, DbTxn* txn)
- {
- return iterator(find_impl(&k, txn ? txn->get_DB_TXN() : NULL, DB_SET, BOOST_CURRENT_FUNCTION));
- }
- iterator lower_bound(const Key& k, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k, txn, DB_SET_RANGE, BOOST_CURRENT_FUNCTION));
- }
- iterator lower_bound(const Key& k, DbTxn* txn)
- {
- return iterator(find_impl(&k, txn ? txn->get_DB_TXN() : NULL, DB_SET_RANGE, BOOST_CURRENT_FUNCTION));
- }
- bool insert(const std::pair<Key,Val>& kv, DB_TXN* txn = NULL)
- {
- return insert_impl(&kv.first, &kv.second, DB_NOOVERWRITE, txn, BOOST_CURRENT_FUNCTION);
- }
- bool insert(const std::pair<Key,Val>& kv, DbTxn* txn)
- {
- return insert_impl(&kv.first, &kv.second, DB_NOOVERWRITE, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- bool insert(const Key& k, const Val& d, DB_TXN* txn = NULL)
- {
- return insert_impl(&k, &d, DB_NOOVERWRITE, txn, BOOST_CURRENT_FUNCTION);
- }
- bool insert(const Key& k, const Val& d, DbTxn* txn)
- {
- return insert_impl(&k, &d, DB_NOOVERWRITE, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- void replace(const std::pair<Key,Val>& kv, DB_TXN* txn = NULL)
- {
- insert_impl(&kv.first, &kv.second, 0, txn, BOOST_CURRENT_FUNCTION);
- }
- void replace(const std::pair<Key,Val>& kv, DbTxn* txn)
- {
- insert_impl(&kv.first, &kv.second, 0, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- void replace(const Key& k, const Val& d, DB_TXN* txn = NULL)
- {
- insert_impl(&k, &d, 0, txn, BOOST_CURRENT_FUNCTION);
- }
- void replace(const Key& k, const Val& d, DbTxn* txn)
- {
- insert_impl(&k, &d, 0, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key& k, DB_TXN* txn = NULL)
- {
- return remove_impl(&k, txn, BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key& k, DbTxn* txn)
- {
- return remove_impl(&k, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- bool erase(iterator& iter)
- {
- return iter.remove();
- }
- void clear(DB_TXN* txn = NULL)
- {
- clear_impl(txn, BOOST_CURRENT_FUNCTION);
- }
- void clear(DbTxn* txn)
- {
- return clear_impl(txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- DB* getDB() { return m_db; }
- const DB* getDB() const { return m_db; }
- };
- } // namespace febird
- #endif // __febird_bdb_dbmap_h__
file: dbmap.cpp
- /* vim: set tabstop=4 : */
- #include "dbmap.h"
- #include <sstream>
- /**
- @brief when iterate from end to begin
- @code
- for (dbmap<Key, Val>::iterator iter = dbm.end();;)
- {
- --iter;
- if (!iter.exist()) break;
- pair<Key,Val>& kv = *iter;
- // do some thing
- }
- @endcode
- */
- namespace febird {
- dbmap_iterator_impl_base::dbmap_iterator_impl_base(class dbmap_base* owner)
- : m_owner(owner)
- , m_curp(0), m_ret(-1)
- {
- }
- void dbmap_iterator_impl_base::init(DB* dbp, DB_TXN* txn, const char* func)
- {
- int ret = dbp->cursor(dbp, txn, &m_curp, 0);
- if (0 != ret)
- {
- delete this;
- std::ostringstream oss;
- oss << db_strerror(ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- m_ret = 0;
- }
- dbmap_iterator_impl_base::~dbmap_iterator_impl_base()
- {
- if (m_curp)
- m_curp->close(m_curp);
- }
- void dbmap_iterator_impl_base::advance(u_int32_t direction_flag, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- DBT tk; memset(&tk, 0, sizeof(DBT));
- DBT td; memset(&td, 0, sizeof(DBT));
- m_ret = m_curp->get(m_curp, &tk, &td, direction_flag);
- if (0 == m_ret)
- {
- load_key(tk.data, tk.size);
- load_val(td.data, td.size);
- }
- else if (DB_NOTFOUND != m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(m_ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- /**
- @brief
- @return true successful updated
- false (key, d.key2) did not exist, not updated
- @throw other errors
- */
- void dbmap_iterator_impl_base::update(const void* d, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- this->save_key(oKey1);
- m_owner->save_val(oData, d);
- DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
- DBT td; memset(&td, 0, sizeof(DBT)); td.data = oData.begin(); td.size = oData.tell();
- int ret = m_curp->put(m_curp, &tk, &td, DB_CURRENT);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- void dbmap_iterator_impl_base::remove(const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- int ret = m_curp->del(m_curp, 0);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- //////////////////////////////////////////////////////////////////////////
- dbmap_base::dbmap_base(DB_ENV* env, const char* dbname
- , DB_TXN* txn
- , bt_compare_fcn_type bt_comp
- , const char* func
- )
- : m_bt_comp(0)
- {
- m_bulkSize = 512*1024;
- m_db = 0;
- int ret = db_create(&m_db, env, 0);
- if (0 == ret)
- {
- if (bt_comp) {
- m_bt_comp = bt_comp;
- m_db->set_bt_compare(m_db, bt_comp);
- }
- m_db->app_private = (this);
- int flags = env->open_flags & (DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
- ret = m_db->open(m_db, txn, dbname, dbname, DB_BTREE, DB_CREATE|flags, 0);
- }
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- dbmap_base::~dbmap_base()
- {
- if (m_db)
- m_db->close(m_db, 0);
- }
- dbmap_iterator_impl_base* dbmap_base::begin_impl(DB_TXN* txn, const char* func)
- {
- dbmap_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- DBT tk; memset(&tk, 0, sizeof(DBT));
- DBT td; memset(&td, 0, sizeof(DBT));
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk, &td, DB_FIRST);
- if (0 == iter->m_ret)
- {
- iter->load_key(tk.data, tk.size);
- iter->load_val(td.data, td.size);
- }
- else if (DB_NOTFOUND != iter->m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(iter->m_ret)
- << "... at: " << func;
- delete iter; iter = 0;
- throw std::runtime_error(oss.str());
- }
- return iter;
- }
- dbmap_iterator_impl_base* dbmap_base::end_impl(DB_TXN* txn, const char* func)
- {
- dbmap_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- // iter->m_ret = DB_NOTFOUND;
- return iter;
- }
- dbmap_iterator_impl_base* dbmap_base::find_impl(const void* k, DB_TXN* txn, u_int32_t flags, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- save_key(oKey1, k);
- DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
- DBT td; memset(&td, 0, sizeof(DBT));
- dbmap_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk, &td, flags);
- if (0 == iter->m_ret)
- {
- iter->load_key(tk.data, tk.size);
- iter->load_val(td.data, td.size);
- }
- else if (DB_NOTFOUND != iter->m_ret && DB_KEYEMPTY != iter->m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(iter->m_ret)
- << "... at: " << func
- << "\n"
- << "flags=" << flags
- ;
- throw std::runtime_error(oss.str());
- }
- return iter;
- }
- /**
- @brief insert a record
- @return true success, no same k-k2 in db, the record was inserted
- false failed, has same k-k2 in db, the record was not inserted, not replaced existing yet
- @throws exception, failed
- */
- bool dbmap_base::insert_impl(const void* k, const void* d, u_int32_t flags, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- try {
- save_key(oKey1, k);
- save_val(oData, d);
- }
- catch (const IOException& exp)
- {
- std::ostringstream oss;
- oss << exp.what() << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
- DBT td; memset(&td, 0, sizeof(DBT)); td.data = oData.begin(); td.size = oData.tell();
- int ret = m_db->put(m_db, txn, &tk, &td, flags);
- if (DB_KEYEXIST == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "\n"
- ;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief
- @return true (k) existed, remove success
- false (k) not existed, nothing done
- */
- bool dbmap_base::remove_impl(const void* k, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- save_key(oKey1, k);
- DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
- int ret = m_db->del(m_db, txn, &tk, 0);
- if (DB_NOTFOUND == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "\n"
- ;
- throw std::runtime_error(oss.str());
- }
- void dbmap_base::clear_impl(DB_TXN* txn, const char* func)
- {
- u_int32_t count;
- int ret = m_db->truncate(m_db, txn, &count, 0);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "\n"
- ;
- throw std::runtime_error(oss.str());
- }
- }
- } // namespace febird
-
项目地址:http://code.google.com/p/febird
发表评论
-
检查序列化声明的顺序和成员定义的顺序
2009-04-11 16:12 1295项目地址:http://code.google.com/p/f ... -
febird.dataio 序列化宏
2009-04-08 11:23 1066序列化宏 DATA_IO_LOAD_SAVE( ... -
最便捷、最强大、速度最快的C++序列化框架
2008-11-07 18:08 2111最便捷、最强大、速度最快的C++序列化框架。 特别注意 ... -
持久化的多键映射,使用BerkeleyDB
2008-11-07 18:29 1226项目地址:http://code.goog ... -
序列化如何简洁地支持XML
2009-01-02 14:24 991目前该框架(DataIO)仅支持二进制。想起序列化支持只需要一 ... -
febird.dataio 优化技术
2009-04-04 12:45 1332优化技术主要有以下几点: 1. 优化的inl ... -
febird.dataio和boost.serialization性能对比
2009-04-06 20:07 1598和boost.serialization性能对比 运行 ... -
febird.dataio vs boost.serialization 运行性能对比
2009-04-06 20:09 1075代码表示的是数据格式,DATA_IO_LOAD_SAVE 在 ...
相关推荐
- **数据持久化**:支持多种方式的数据持久化,如快照、日志记录等。 - **数据压缩**:内置多种压缩算法以减少存储空间需求。 - **数据加密**:提供数据加密功能,保护敏感信息的安全。 #### KC的性能 ...
非持久化存储,如内存中的Redis、Berkeley DB和Memcached,提供了高速的读写性能,常作为缓存来提升系统响应速度,减轻持久化存储的压力。 接着,数据处理层主要分为批量处理(离线处理)和实时处理(在线处理)。...
Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。Redis 使用的一些心得体会的笔记。 在本笔记中,我们将详细介绍 Redis 的基本概念、...
2. **非持久化存储**:如Redis、Berkeley DB和Memcached,它们存储在内存中,提供快速读写但不持久化,常作为缓存来加速数据访问。 **三、数据处理层** 数据处理层分为批量处理(离线处理)和实时处理(在线处理)...
JDBM2与其他键值对存储系统(如Berkeley DB Java Edition或LevelDB)相比,可能具有不同的特性和优势。比如,JDBM2是纯Java实现,可以在任何Java运行环境中使用,而无需安装额外的依赖。此外,JDBM2的API设计简洁,...
### Redis 教案笔记 #### 一、Redis简介与NoSQL...以上内容涵盖了Redis的基本概念、安装配置、客户端使用、数据类型、持久化策略、主从复制与集群技术等多个方面,希望能够帮助读者全面了解Redis的特性和应用场景。
`lmdb`在Python中的应用主要涉及到数据持久化、高速查找和低延迟的数据访问场景。 **1. LMDB的特点** - **内存映射**:LMDB使用内存映射文件技术,将数据库存储直接映射到进程地址空间,极大地提高了读取速度。 - ...
1. **键值(Key-Value)存储数据库**:如TokyoCabinet/Tyrant、Redis、Voldemort、BerkeleyDB等。这类数据库最适合用于内容缓存,尤其是面对高访问负载时表现出色。 2. **列存储数据库**:例如Cassandra、HBase、Riak...
LMDB(Lightning Memory-Mapped Database)是一种高效、小巧、基于内存映射的键值存储系统,由Berkeley DB的作者之一Jeffrey Stedfast开发。这个“lmdb-mdb.master.rar”压缩包包含了LMDB数据库在Windows平台上的...