面试题答案
一键面试- 通过_rev字段管理版本及避免并发混乱:
- 版本标识:在CouchDB中,每个文档都有一个
_rev
字段,它是文档版本的唯一标识。每次文档被更新,_rev
字段的值都会改变。例如,初始文档的_rev
可能是1 - 1234567890abcdef
,第一次更新后可能变为2 - 1234567890abcdef
。 - 乐观并发控制:客户端在更新文档时,需要在请求中包含当前文档的
_rev
值。CouchDB会将客户端提供的_rev
与服务器上存储的文档_rev
进行比较。如果两者相同,说明自客户端获取文档后没有其他客户端对其进行修改,更新操作可以成功执行,同时_rev
会更新为新的值。如果_rev
不匹配,说明文档已被其他客户端修改,CouchDB会返回冲突错误(HTTP 409状态码)。客户端在收到冲突错误后,需要重新获取最新版本的文档,合并更改,然后再次尝试更新。 - 对于复杂文档结构:即使文档包含嵌套数组和对象,原理也是一样的。
_rev
字段管理整个文档的版本,无论文档内部结构多么复杂。例如,一个包含嵌套数组和对象的文档如下:
- 版本标识:在CouchDB中,每个文档都有一个
{
"_id": "example - doc",
"_rev": "1 - 1234567890abcdef",
"data": {
"nestedObject": {
"key1": "value1",
"key2": "value2"
},
"nestedArray": [1, 2, 3]
}
}
当客户端更新nestedObject
中的key1
值时,请求中必须包含当前的_rev
值1 - 1234567890abcdef
。如果服务器上的_rev
与之匹配,更新成功,_rev
会变为新值,如2 - 1234567890abcdef
。
2. 处理部分更新时_rev字段的协同工作:
- 部分更新请求:CouchDB支持对文档进行部分更新。例如,使用
_update
函数或者直接通过HTTP请求修改文档的部分内容。在部分更新时,同样需要在请求中包含当前文档的_rev
值。 - 示例:假设我们只想更新上述文档中
nestedArray
的第一个元素。客户端发送的更新请求可能如下(以HTTP请求为例):
PUT /your - db/your - doc?rev = 1 - 1234567890abcdef
{
"data": {
"nestedArray": [4, 2, 3]
}
}
CouchDB会检查提供的_rev
值与服务器上文档的_rev
是否一致。如果一致,执行部分更新,_rev
更新为新值。如果不一致,返回冲突错误,客户端需重新获取最新文档并重新尝试更新。这样,_rev
字段确保了部分更新在并发环境下的一致性,即使只更新文档的一小部分,也能防止不同客户端的并发更新导致数据混乱。