参考源:参考来源
MongoDB的数据安全包括以下几个概念:
1.恢复日志(Journal)
2.写关注(也叫写安全机制)(Write Concern)
Journal目的:
用来解决因为系统掉电或者崩溃导致内存数据丢失问题的一种日志
在MongoDB 2.0之前,Journal没有被支持或者不是一个默认开的选项
简单来说,数据在写入内存之后即刻返回给应用程序。而数据刷盘动作则在后台由操作系统来进行。MongoDB会每隔60秒强制把数据刷到磁盘上。那么大家可以想象得到,
如果这个时候发生了系统崩溃或者掉电,那么未刷盘的数据就会彻底丢失了
自从2.0开始,MongoDB已经把Journal日志设为默认开启
MongoDB会先把数据更新写入到Journal Buffer里面然后再更新内存数据,然后再返回给应用端。
Journal会以100ms的间隔批量刷到盘上。这样的情况下,即使出现断电数据尚未保存到文件,
由于有Journal文件的存在,MongoDB会自动根据Journal里面的操作历史记录来对数据文件重新进行追加。
有细心的同学可能注意到,Journal文件是100ms 刷盘一次。那么要是系统掉电正好发生在上一次刷journal的50ms之后呢?
这个时候,我们就可以来看一下MongoDB持久化的下一个概念了:写关注
写关注(Write Concern)
写关注(或翻译为写安全机制)是MongoDB特有的一个功能。
它可以让你灵活地指定你写操作的持久化设定。
这是一个在性能和可靠性之间的一个权衡
写关注有以下几个级别:
1.{w: 0} Unacknowledged
Unacknowledged指的是对每一个写入操作,MongoDB并不会返回一个是否成功的状态值。
这个级别是写入性能最好但也是最不安全的级别。
比如说,
你试图插入一个违反了唯一性的文档(重复的身份证号),那么MongoDB会拒绝写入并报错。
但是由于驱动端并没有在乎你的报错,应用程序还满心欢喜以为一切都没问题,下回再来查询那条数据的时候就会出现数据缺失的情况。
有不少时候MongoDB用来保存一些监控和程序日志数据,这个时候如果你有1、2条数据丢失,是不会对应用程序有什么影响的。
基于这些MongoDB早些时候不成熟考量,MongoDB在2.2之前的默认设置就是 {w:0}。
这是个让MongoDB 悔恨无比的选择,因为这个是很多人觉得MongoDB数据不安全的根本原因。
2.{w: 1} Acknowledged
在MongoDB 2.4,这个设置已经被改为下面的 {w:1}
Acknowledged 的意思就是对每一个写入MongoDB都会确认操作的完成状态,不管是成功还是失败。
当然这个确认只是基于主节点的内存写入。
但就是这个级别,可以侦测到重复主键, 网络错误,系统故障或者是无效数据等错误。
自2.4版本起,MongoDB的默认写安全设置就是 {w:1} Acknowledged
在这种情况下,出现因为系统故障掉电原因而导致的数据丢失只会是我们早些提到的日志没有及时刷盘的情况。
如果你不能接受因为系统崩溃而引起的可能的100ms的数据损失,那么你可以选用下一个级别: {j:1} Journaled
3.{j:1} Journaled
使用这种方式意味着每一次的写操作会在MongoDB实实在在的把journal落盘以后才会返回
MongoDB并不会对每一个操作都立即刷盘,而是会等最多30ms,把30ms内的写操作集中到一起,采用顺序追加的方式写入到盘里
在这30ms内客户端线程会处于等待状态
4.{w: “majority”}
写到多数节点
使用这个写安全级别,MongoDB只有在数据已经被复制到多数个节点的情况下才会向客户端返回确认
总结
一般来说,MongoDB建议在集群中使用 {w: “majority”} 设置。
在一个集群是健壮的部署的情况下(如:足够网络带宽,机器没有满负荷),这个可以满足绝大部分数据安全的要求,
因为MongoDB的复制在正常情况下是毫秒级别的,往往在Journal刷盘之前已经复制到从节点了。如果你追求完美,那么可以再进一步使用{j:1} 。两者相结合,
传说中MongoDB 丢数据的事情,确实已经成为传说了。
注:
java Driver
首先列一下WriteConcern的几种抛出异常的级别参数:
WriteConcern.NONE:没有异常抛出
WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常
WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。
WriteConcern.FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。
java DriverAPI的insert,update,remove方法中均有可以设置此参数的方法.
来源:参考来源