下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

NoSQL数据库的事务处理与一致性

作者:课课家教育     来源: http://www.kokojia.com点击数:1463发布时间: 2017-08-28 09:30:55

标签: 数据库NoSQL数据库事务

  随着互联网的发展,Nosql数据库开始流行起来。相比传统关系型数据库,NoSQL数据库可以说是为性能而生,但是在事务处理与一致性方面的能力明显不足,而这方面又是一个数据库产品不能不去面对的。下面我们先来看一下什么是数据库的一致性:

  NoSQL数据库:数据的一致性

  读取一致性

  1、强一致性

  在任何时间访问集群中任一结点,得到的数据结果一致;

  2、用户一致性

  ①对同一用户,访问集群期间得到的数据一致;

  ②解决用户一致性:使用粘性会话,将会话绑定到特定结点来处理;

  ③这样会降低负载均衡器的性能;

  3、最终一致性

  集群中各结点间由于数据同步不及时造成暂时的数据不一致,但数据同步完成后,最终具有一致性;

  更新一致性

  1、悲观方式

  ①使用写锁

  ②大幅降低系统响应能力

  ③可能导致死锁

  2、乐观方式

  ①先让冲突发生,再检测顺序

  ②自动合并的处理方式极具“领域特定”问题

  放宽“一致性约束”

  1、CAP定理

  ①一致性(Consistency)、可用性(Availability)和分区耐受性(Partitiontolerance),3个属性只可能同时满足2个;

  ②分区耐受性的解释:集群因通信故障而划分为多个时仍然可用

  2、CA系统

  ①单服务器

  ②集群中出现”分区“,就不可用

  3、PA/PC

  ①集群出现”分区“时,需要在”一致性“和“可用性”间权衡

  ②一般会牺牲部分一致性(eg:使用最终一致性),保证可用性

  放宽“持久性”约束

  更严格的持久性,意味着更多的性能损失;

  1、牺牲“持久性”换取更好的性能

  2、复制“持久性”故障

  ①主节点故障,未同步到从节点的数据丢失

  ②主节点恢复,故障期间更新的数据冲突

  ③解决方案:针对单个请求指定其所需的持久性

  2、复制“持久性”故障    ①主节点故障,未同步到从节点的数据丢失    ②主节点恢复,故障期间更新的数据冲突    ③解决方案:针对单个请求指定其所需的持久性

  看完以上关于数据库一致性的相关介绍,接下来我们来了解一下NoSQL数据库产品:以Memcache、Redismongodb这三种当前最炙手可热的数据库为例,介绍一下它们各自是如何处理这一问题的!

  1.Memcache

  Memcache在操作数据是执行以下步骤:取得数据(get命令)、修改i数据、保存数据(set命令)。这三步是单独进行,当多个不同的终端对同一个key值进行操作,即使时间再短,也存在发生不一致的可能。因此,Memcache提供了CAS(CheckandSet)操作,来保证数据的一致性。CAS操作提供了两个命令,gets和cas来替代get和set命令。gets命令读取数据时会同时读取该key值得一个版本号(casid)。casid是数据的版本号,在更新数据时肯定会发生改变。cas命令进行更新时,要求提供版本号(casid),这时就就可以把刚才gets都出来版本号传给它。cas命令会比较这个版本号与数据库中key值得当前版本号,只有两者一致,保存才会成功。如果不一致,说明服务器上该数据已经被其它进程改变,保存就会失败。Memcache就是通过这个类似乐观锁的机制,保证数据的原子操作。

  2.Redis

  Redis对事务的处理是比较简单的,它只能保证一个client发起的事务中的命令可以连续执行,不会被其它client的命令插入。当一个client发出multi命令时,就开启了事务,后续命令不会立即执行,而是放到一个队列中,知道执行了exec命令,Redis会顺序执行队列中的所有命令。discard命令可以退出事务,也就是清空队列中的所有命令,类似于事务回滚。但是实际上Redis并不是真正意义上的回滚,如果执行exec命令,当某操作发生错误,后续操作不再执行,但队列中已执行成功的命令不会回滚。这时Redis需要改进之处。Redis也有乐观锁机制,来保证数据一致性。它使用watch命令来监视给定的key,当执行exec时,如果监视的key从调用watch后发生了变化,则整个事务会失败。也可以调用watch多次监视多个key。注意,watch的key对整个连接有效,事务也一样。如果连接断开,监视和事务都会自动清除。执行exec、discard、unwatch命令都会清除连接中的所有监视。

  3.Mongodb

  Mongodb的数据一致性,可以通过findAndModify命令来实现。这个命令可以将查询(find)和修改(modify)作为一个原子操作来进行,从而保证了数据的一致性。findAndModify命令既有“update”键也有“remove”键,但两者只能同时出现一个。mongodb的很多命令都是保证是原子操作(atomic)像:$inc,$set等。

  MongoDB数据库中操作单个文档总是原子性的,然而,涉及多个文档的操作,通常被作为一个“事务”,而不是原子性的。相对于其它NoSQL数据库的简陋,Mongodb可谓功能强大,它被认为是最接近关系型数据库的NoSQL产品了。但是非常遗憾,它并不支持事务和锁机制。如果要实现“事务”,只能由客户端程序通过两阶段提交的方式来模拟了。例如可以通过以下步骤:

Mongodb的数据一致性,可以通过findAndModify命令来实现。这个命令可以将查询(find)和修改(modify)作为一个原子操作来进行,从而保证了数据的一致性。findAndModify命令既有“update”键也有“remove”键,但两者只能同时出现一个。mongodb的很多命令都是保证是原子操作(atomic)像:$inc,$set等。    MongoDB数据库中操作单个文档总是原子性的,然而,涉及多个文档的操作,通常被作为一个“事务”,而不是原子性的。相对于其它NoSQL数据库的简陋,Mongodb可谓功能强大,它被认为是最接近关系型数据库的NoSQL产品了。但是非常遗憾,它并不支持事务和锁机制。如果要实现“事务”,只能由客户端程序通过两阶段提交的方式来模拟了。例如可以通过以下步骤:

  第1步:先记录一条事务记录,将要修改的多行记录的修改值写到里面,并设置其状态为init(如果这时候操作中断,那么在重新启动时,会判断到它处于init状态,从而将其保存的多行修改操作应用到具体的行上)。

  第2步:然后更新具体要修改的行,将刚才写的事务记录的标识写到它的tran字段中。

  第3步:将事务记录的状态从init变成pending(如果在这时候操作中断,那么在重新启动时,会判断到它的状态是pending,这时查看其所有对应的多条要修改的记录,如果其tran值不为空,那么就进行第4步;如果值为空,说明第4步已经执行过了,直接将其状态从pending变成commited就行)。

  第4步:将需要修改的多条记录的相应值加以修改,并且unset掉之前的tran字段。

  第5步:将事务记录那一条的状态从pending变成commited,事务至此完成。

  小编结语:

  更多内容尽在课课家教育!

赞(24)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程