面试题答案
一键面试可能导致冲突的原因
- 并发修改:多个客户端同时尝试修改或删除同一文档,CouchDB 使用基于修订版本号(
_rev
)来跟踪文档变化。如果一个客户端在另一个客户端获取文档后但在删除前修改了文档,就会产生冲突。例如,客户端A获取文档doc1
及其_rev
为1-abc
,在A准备删除doc1
时,客户端B修改了doc1
,此时doc1
的_rev
变为2-def
,当A执行删除操作时,就会因为_rev
不匹配而冲突。 - 网络延迟:在网络不稳定或延迟较高的情况下,批量删除请求可能部分成功,部分失败。例如,批量删除请求中有10个文档,前5个文档删除成功,后5个文档由于网络延迟,CouchDB 服务器状态发生变化(如其他客户端修改了相关文档),导致后5个文档删除失败并产生冲突。
检测冲突
- 响应状态码:CouchDB 在发生冲突时,会返回HTTP 409状态码。在批量删除操作后,检查响应状态码,如果是409,则表明发生了冲突。例如,使用
curl
进行批量删除请求:
curl -X POST -H "Content-Type: application/json" -d '{"docs":[{"_id":"doc1","_rev":"1-abc"},{"_id":"doc2","_rev":"1-def"}]}' http://localhost:5984/mydb/_bulk_docs
如果响应状态码为409,说明有冲突发生。 2. 响应体:响应体中会包含具体冲突的文档信息。CouchDB 返回的响应体类似如下格式:
{
"results": [
{
"error": "conflict",
"reason": "Document update conflict.",
"id": "doc1",
"rev": "3-xyz"
},
{
"ok": true,
"id": "doc2",
"rev": "2-uvw"
}
]
}
通过解析响应体,可以明确哪些文档发生了冲突以及冲突的原因。
处理冲突
- 重试:最简单的方法是在检测到冲突后,重新获取冲突文档的最新
_rev
,然后再次发起删除请求。例如,在检测到doc1
冲突后:
# 获取doc1最新信息
curl -X GET http://localhost:5984/mydb/doc1
# 得到最新的_rev,假设为3-xyz,重新发起删除请求
curl -X DELETE http://localhost:5984/mydb/doc1?rev=3-xyz
- 合并或解决冲突:在某些复杂场景下,可能需要根据业务逻辑对冲突进行合并处理。比如多个客户端对同一文档的不同字段进行了修改,此时可以将这些修改合并后重新保存文档,再进行删除操作。
性能优化
- 减少请求次数:尽量一次性批量删除更多文档,减少与服务器的交互次数。例如,将原本多次小批量的删除请求合并为一次较大批量的请求。但要注意避免请求体过大导致网络传输问题或服务器资源耗尽。
- 并行处理:如果客户端支持并行操作,可以将批量删除操作分成多个子任务并行执行。例如,使用多线程或异步编程技术,将文档分成几组同时发起删除请求,提高整体删除效率。但要注意处理好并发控制,避免因为并发操作导致更多冲突。
- 预获取修订版本:在进行批量删除前,一次性获取所有要删除文档的最新
_rev
,减少因为_rev
不匹配导致的冲突重试次数。例如,先通过_all_docs
API获取所有文档的_id
和_rev
,然后再进行批量删除。
# 获取所有文档的_id和_rev
curl -X GET http://localhost:5984/mydb/_all_docs?include_docs=true
- 优化网络配置:确保网络稳定且带宽充足,减少因为网络延迟或丢包导致的操作失败和重试。可以采用优化网络拓扑、调整网络设备参数等方式提升网络性能。