科技小数据|NoSQL数据库,Couchbase完美的分布式( 二 )


科技小数据|NoSQL数据库,Couchbase完美的分布式
文章图片
从图上可以看出 , 增加新的节点就可以扩展总的可用内存 , 从而增加存储的数据量 。 通过bucket限额系统可以判断数据是否应该调出内存 。
vBucket
vBucket相当于一个key的子集 , 保存的是客户端存储对象的key值 , vBuckets用于在集群的节点间分配数据和备份数据 。 是couchbase实现autosharding , 在线动态增减节点的重要基础 。 不是用户可访问的组件 , 但是至关重要 。
通过vbucket , 客户端直接访问保存信息的服务器 , 不需要通过中间代理或者其他架构 , 因此可以从数据中抽象出物理拓扑结构 。 这种方式使couchbase易扩展 。
这种架构不同于memcached使用的架构 , memcached的做法是用key算出一个hash , 得到服务器列表中的对应服务器 。 这个列表需要动态维护 , 还需要一个hash算法用于处理集群拓扑结构的变化 。
如以下代码所示:
servers=['server1:111','server2:112','server3:113']server_for_key(key)=servers[hash(key)%servers.length]
这种算法很简单 , 也很容易理解 , 但也有几个问题:
1、如果一台服务器失效 , 会造成该分片的所有key失效 。
2、如果服务器容量不同 , 管理非常麻烦 。
3、运维、配置非常不方便 。
为了把key跟服务器解耦 , couchbase引入了vBucket 。 每个key都属于一个vbucket , 查找对应的value时先用hash函数计算这个key属于哪个vbucket , 再从vBucket与服务器对应表中查找这个vbucket属于哪个服务器 , 映射表保存vbucket和服务器的对应关系 , 一个bucket一行 , 一个服务器可以对应多个vbucket 。
1、keyhash对应一个vBucket , 不再直接对应服务器 。
2、集群维护一个全局的vBucket与服务器对应表 。
例如 , 集群中有3个服务器 , 客户端要查找一个key对应的value值 , 首先计算key属于哪个Vbucket , 在这个例子中 , hash结果是vB8 , 通过查映射表 , 客户端确定vB8对应到服务器C , 然后get操作直接发送到服务器C 。
科技小数据|NoSQL数据库,Couchbase完美的分布式
文章图片
一段时间后 , 需要加一个新的服务器D到集群 , vbuckets映射表更新为:
科技小数据|NoSQL数据库,Couchbase完美的分布式
文章图片
这时 , 客户端再想取key对应的value值 , hash算法结果仍为vB8 , 但是新的映射表会将vB8映射到服务器D 。
由于vBucket把key跟服务器的静态对应关系解耦合 , 基于vBucket可以实现一些非常强大有趣的功能 , 例如:
Replica , 以vBucket为单位的主从备份 。 如果某个节点失效 , 只需要更新vBucket映射表 , 马上启用备份数据 。
动态扩容 。 新增加一个节点后 , 可以把部分vBucket转移到新节点上 , 并更新vBucket映射表 。
缓存管理
Couchbase自动管理缓存层 , 确保有足够的内存空间以维持性能 。 couchbase后台有个进程 , 专门把一定时间没有被访问的数据移出内存 , 这个进程的扫描时间和数据的最大无活动时间都是可以设置的 。 couchbase在对数据进行增删时会先体现在内存中 , 而不会立刻体现在硬盘上 , 从内存的修改到硬盘的修改这一步骤是由couchbase自动完成 , 等待执行的硬盘操作会以writequeue的形式排队等待执行 , 也正是通过这个方法 , 硬盘的I/O效率在writequeue满之前是不会影响couchbase的吞吐效率的 , 而writequeue的长度是可以设置的 。 通过writequeue执行大量写数据库操作时用户可能会感受到很短时间的内存飙升 , 但是异步特性和queue的使用使读写速度都非常快 。
对于所有文档couchbase都会建立一个额外的56byte的metadata , 这个metadata功能之一就是表明数据状态是否活动在内存中 。 同时文档的id也作为标识符和metadata一起长期活动在内存中 。 这表示对文档id不存在的情况服务器可以直接返回‘文档id不存在 。 couchbase官方建议bucket申请的内存中 , metadata和key所占用的内存不应超过一半 , 否则couchbase的性能会显著下降 。 为了保证这个条件 , 当有效数据占用超过一定内存时就需要把超额数据移除了 。