目次
一、MongoDB简介
二、MongoDB锁机制
三、锁的实践影响
3.1 高并发写入导致的写锁案例
一、MongoDB简介
MongoDB 作为一种非关系型文档数据库,在当代应用中扮演着极其重要的角色,尤其在处置惩罚大规模、高并发、灵活数据模子的场景下。MongoDB 具有如下特点:
- MongoDB 拥有丰富的数据模子,而且文档没有固定的模式,这为扩展性提供了便利
- 高可扩展性:MongoDB 设计之初就考虑到了扩展性,支持分片(sharding),可以轻松跨越多台服务器分配数据和处置惩罚请求,从而实现水平扩展。这对于处置惩罚海量数据等场景只管重要。
- 高性能:MongoDB 支持各种索引,可以大概加锁数据的查询;接纳异步非阻塞 I/O 模子,避免了线程的同步等待,从而实现高效的读写性能;水平扩展能力也能提高性能,通过添加分片可来分散负载,保持高性能;接纳预分配数据机制来提高性能,当要写入新数据时,不会比及写入时才去请求磁盘空间,而是提前预留肯定空间;同时还支持批量操作,减少交互来提升性能。
- 高可用性:利用副本集来对数据进行冗余保存,当主节点故障时,数据也不会丢失。
MongoDB 作为一个多用户、多线程的 NoSQL 数据库,确保其在高并发访问下数据的一致性和完整性至关重要。如果没有有效的并发控制机制,可能会产生如脏读、不接重复度、幻读等一系列问题。
那如何确保 MongoDB 在并发情况下可以大概保障数据一致性和完整性呢?那就是 MongoDB 的锁机制。
二、MongoDB锁机制
MongoDB 锁机制是其并发控制的重要组成部分,目标是为了确保多线程多用户访问下数据的完整性和一致性,重要分类两大类:MMAPv1 引擎的锁机制和 WiredTiger 引擎的锁机制。
在利用 MMAPv1 存储引擎的 MongoDB 版本中,全局锁时其重要的并发控制手段。全局锁有两种模式:
- 读锁:允很多个读操作共享,但构造任何写操作
- 写锁:独占锁,一旦获取将构造其他读写操作,直至锁释放
WiredTiger 引擎利用了更细粒度的锁机制,重要为:
- 文档锁:锁定单个文档,允很多个并发读操作,但写操作会互斥。这大大减少了锁竞争,提高了并发写入能力,从而使得在高并发场景下也能保持较好的性能。
- 多版本并发控制(MVCC):WiredTiger 实现了一种 MVCC 机制,为每个事务创建数据的多个版本。如许,读操作可以不受写操作的影响,看到事务开始时的一致性视图,而写操作则在新版本上进行,直到事务提交后才会对外可见。这增强了体系的并发能力,同时包管了事务的隔离性。
- 范围锁:在某些情况下,为了保持数据一致性,WiredTiger可能会锁定一个文档范围,防止其他操作修改该范围内的数据。
- 乐观锁:除了传统的锁机制,WiredTiger还接纳了乐观锁策略,尤其在处置惩罚读写操作时。乐观锁依赖于文档版本控制,每个文档都有一个内部版本号。写操作前先读取版本号,写入时查抄版本号是否改变,若未变则成功,否则重试。这种方式减少了锁的利用,提高了并发效率
三、锁的实践影响
WiredTiger 提供文档级锁,减少了写操作之间的锁竞争,提高了并发性能。支持压缩,可以大概减少存储空间需求和I/O操作,进而提升读写速度。利用多版本并发控制(MVCC),允许读操作不阻塞写操作,提升了读取性能。支持事务,增强了数据一致性。
但是有更高的内存需求,因为其缓存策略会占用较多内存。在极度并发写入场景下,虽然概率较低,但仍有可能遇到锁竞争导致的性能瓶颈。
MongoDB 利用 WiredTiger 存储引擎时,具备肯定的死锁检测和处置惩罚能力,旨在减少乃至避免死锁对体系的影响。
WiredTiger 存储引擎具有内置的死锁检测机制。当事务等待资源高出肯定时间阈值,引擎会实验检测是否存在死锁情况。如果检测到死锁,WiredTiger 会选择一个或多个事务进行回滚,通常是那些影响较小大概等待时间较长的事务,从而解除死锁状态。
可以通过以下方式避免死锁
- 尽可能收缩事务运行时间,减少对锁的持偶尔间,可以低落与其他事务辩说的概率。利用原子操作和批量操作可以减少单独锁的次数和持续时间。
- 设计事务时,尽量按照一致的次序访问资源,减少循环等待的可能性。比方,如果多个事务总是按照相同的资源访问次序执行,那么死锁就不会发生。
- 在应用层面实行适当的并发控制策略,如乐观锁或悲观锁的公道利用,以及公道的重试逻辑,可以在遇到锁辩说时优雅地处置惩罚,避免直接导致死锁。
3.1 高并发写入导致的写锁案例
在利用MongoDB 时,由于有高并发的写入,突然出现了大量获取链接的报错,具体报错信息如下:
- org.springframework.data.mongodb.UncategorizedMongoDbException: Too many operations are already waiting for a connection. Max number of operations (maxWaitQueueSize) of 500 has been exceeded.; nested exception is com.mongodb.MongoWaitQueueFullException: Too many operations are already waiting for a connection. Max number of operations (maxWaitQueueSize) of 500 has been exceeded.
- at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:138)
- at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2902)
- at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:587)
- at org.springframework.data.mongodb.core.MongoTemplate.doUpdate(MongoTemplate.java:1636)
- at org.springframework.data.mongodb.core.MongoTemplate.upsert(MongoTemplate.java:1570)
复制代码 通过监控发现是高并发写入引起了写锁,导致某些操作长时间占用写锁,最终获取不到毗连导致出现上面的问题。下面来分析下原因。
并发写入操作频繁且锁等待时间较长时,毗连可能会被长时间占用,无法及时归还到毗连池,导致可用毗连耗尽。那如何来解决呢?
我们末了如那边理的呢?实在也很简单,可以接纳批量写入来减少锁竞争或锁等待时间,大概接纳异步的方式来进行写入操作。
还需要查抄下设置的毗连池是否公道,可以根据情况适当的调解毗连池的巨细。
往期经典推荐
Sentinel与Nacos强强连合,构建微服务稳定性基石的重要实践_sentinel和nacos-CSDN博客
云原生:Kubernetes下的Java应用部署实战详解_kubernetes部署java-CSDN博客
全面解读MongoDB高可用、高性能与高可扩展架构-CSDN博客
深入剖析MongoDB集群架构设计_mongodb 架构-CSDN博客
TiDB存储引擎TiKV揭秘-CSDN博客
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |