从底层代码实现探讨不同NoSQL数据库之间的性能差异

2020-05-29 00:00:00 数据 数据库 代码 性能 机制

如今,随着大数据时代的来临,越来越多的人开始跳脱传统的关系型数据库的思维,开始转投NoSQL数据库。这也造成NoSQL数据库市场上也出现百家争鸣的局面。其中MongoDB一马当先,在DB-Engine的数据库影响力排名上达到了第五位,仅次于几个传统的关系型大户。可是MongoDB其实在设计和性能表现上也并不是十全十美的。

国内的SequoiaDB 巨杉数据库作为同类的文档型NoSQL数据库,就在多项性能表现上超越了MongoDB,那么现在我们就要来谈谈两者不同的底层架构对于高性能表现的影响。

1.日志

日志作为数据库非常重要的一个运行机制,不仅直接影响着数据库操作的方式效率,也会影响到其他许多功能的实现。

MongoDB的日志使用的是CappedCollection机制。CappedCollection是一种固定大小的集合,当集合的大小达到指定大小时,新数据就会覆盖老数据。基于这种机制,可以实现“Auto-FIFO”以及Age-Out”的功能。

SequoiaDB的日志则使用的是日志序列号LSN机制,这也是一直被各种数据库所采用的经典日志机制。不仅因为其实现方便,更因为LSN的日志机制可以更好的支持事务功能。

2.锁机制

锁机制也是数据库中重要的一个部分,与性能表现息息相关。

MongoDB对锁的处理相对简单,只有库级粒度的锁,也就是当一个写锁处于占用时,整个库的数据将被锁住,无法使用。虽然设计简洁,且在一般情况下这种机制能发挥很好的作用,但是一旦出现高并发高压力的情况,MongoDB的总体吞吐量就会出现性能的瓶颈。

SequoiaDB的设计理念之一,就是在正常流程下尽可能无锁,异常流程可以使用额外的代码或锁机制保证逻辑正确。这样在遇到像32核的这种大机器下进行高压力并发操作,SequoiaDB也可以把CPU打满,不会在某些代码上出现性能瓶颈。

3.事务

事务也是数据库的重要功能,然而如今的NoSQL基本都没有加入事务功能。

MongoDB也没有事务处理的功能,在原子性的保证方面,其只能做到单个文档级别,不能支持多文件的原子性。

SequoiaDB则在设计之初就融入了事务功能,基于传统的事务日志的机制就是为了更好的实现事务。当然,还有记录锁、表锁这些机制,包括多副本之间数据根据日志的分发同步,节点失效重新选举后日志的同步等一系列机制。都需要为支持事务而量身定制。

4.分区组

在分区组的架构上,MongoDBSequoiaDB都是使用分片Sharding机制,每个分片里采用Master-Slave结构做数据的复制和同步,同时也通过Sharding分片的机制实现了读写分离,保证了实时读写和后台分析同步进行。其中SequoiaDB的分区组使用了自动选举的功能,当主节点(Master)出现问题时,分区会在剩余可用的从数据节点(Slave)中选举出一个佳方案,让其替代故障的主节点作为新的主节点。这样不仅保障了系统的安全,也可以提高系统处理故障的性能。

5.代码优化

代码优化看似一项细节上的工程,但是只有每个细小之处的累积,才能汇聚成性能表现的整体提升,也正是细微之处的优化,才更能体现出产品设计和开发人员精益求精、追求完美的精神。

MongoDB作为当今NoSQL数据库的领头羊,其架构设计和代码编写已经是业内的水准,但是MongoDB在一些部分相对简单的处理反而在后来造成了其一些性能上的瓶颈,比如锁的机制设计的过于粗放。

SequoiaDB在代码优化和精细化设计这部分做了很多工作,譬如上面提到的并发性和锁的这一部分,为了追求尽量无锁的整体架构,投入了大量的时间和精力。此外,SequoiaDB还有很多细节上的优化,比如在性能敏感的代码里面完全不允许使用String这种STL库,就是为了避免这些深度封装的库会引发额外的操作,造成不必要的损耗。

此外,在分布式架构、自动分区等部分,MongoDBSequoiaDB也有许多的不同,这里就不一一赘述了。

高性能的数据库产品,不仅要在设计之初就充分考虑到每一种影响性能的情况和任何可能引起性能瓶颈的操作,在设计上考虑周全,同时也需要在实际开发、测试和应用过程中,针对遇到的情况不断的改进、优化代码。对于NoSQL数据库,因为在应用上与大数据息息相关,所以更加需要充分考虑比如突发性、高并发、多样性等原来不被重视的问题,此外面对大数据的快速海量多变,还应该对代码做好充分的测试和优化,这样才能在实际运用中能做到处变不惊,成为真正高性能的NoSQL数据库!

相关文章