【问题标题】:RIAK get http://host/riak/people/key "not found"RIAK 获取 http://host/riak/people/key “未找到”
【发布时间】:2014-12-19 12:17:27
【问题描述】:

riak 从 2 个服务器处理集群。

riak-admin status | grep ring_members
ring_members : ['riak@server1.local','riak@server2.local',

向server1写入数据

for i in {1..1000}; do
 curl -i -XPOST 'http://server1.local:8098/riak/people/'$i'' -H 'Content-Type:application/json' -d '{"name":"aaron_'$i'"}'
done

在 server1 上关闭 riak:/etc/init.d/riak stop

并使用 server2 获取数据

for i in {1..1000}; do
 curl -v -i http://server2.local:8098/riak/people/$i
done

第一次通过时未读取 10-30% 的数据。在第二遍读取数据。

第一关

curl -i http://server2.local:8098/riak/people/196

About to connect() to server2.local port 8098 (#0)
*   Trying 2.2.2.2... connected
* Connected to server2.local (2.2.2.2) port 8098 (#0)
> GET /riak/people/196 HTTP/1.1
> Host: server2.local:8098
> Accept: */*
< HTTP/1.1 404 Object Not Found
< Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
< Date: Thu, 27 Nov 2014 11:22:25 GMT
< Content-Type: text/plain
< Content-Length: 10

server2.local left intact

* Closing connection #0

  not found

第二遍

curl -i http://server2.local:8098/riak/people/196

* About to connect() to server2.local port 8098 (#0)
*   Trying 2.2.2.2... connected
* Connected to server2.local (2.2.2.2) port 8098 (#0)
> GET /riak/people/196 HTTP/1.1
> Host: server2.local:8098
> Accept: */*
< HTTP/1.1 200 OK
< X-Riak-Vclock: a85hYGBgzGDKBVIcypz/foYkbmfKYEpkzGNlCGh9fZYvCwA=
< Vary: Accept-Encoding
< Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
< Link: </riak/people>; rel="up" 
< Last-Modified: Thu, 27 Nov 2014 11:21:52 GMT
< ETag: "2C4oPFcSctzBX1mwHjjfQ1" 
< Date: Thu, 27 Nov 2014 11:25:47 GMT
< Content-Type: application/json
< Content-Length: 20

* Closing connection #0

 {"name":"aaron_196"}

为什么会这样?

【问题讨论】:

    标签: riak


    【解决方案1】:

    这是由最终一致性、分区容错性和小集群大小共同造成的。

    预选清单

    当您存储密钥时,Riak 会将副本存储在 3 个不同的虚拟节点 (vnode) 中,统称为该密钥的“预置列表”。

    vnode 数量的默认值为 64。因此您的每个节点都有 32 个 vnode。创建集群时,将 vnode 分配给物理节点的算法会尝试在同一物理节点上驻留任何 preflist 中的 vnode 不超过 1 个 - 当只有 2 个节点存在时,这是不可能完成的任务。

    因此,当您存储值时,2 个副本被写入一个节点,一个被写入另一个节点。

    故障状态

    当一个节点发生故障、关闭或以其他方式变得不可用时,其余节点会根据需要启动回退 vnode,以便接受原本由缺失节点的 vnode 处理的操作。当原始节点再次可用时,会触发提示切换过程,导致备用 vnode 将其所有数据发送到原始位置的主 vnode。

    法定人数

    Riak 中的请求取决于 vnode 的法定人数。一些常用的法定人数是:

    • read r - 在向客户端返回值之前必须回复读取请求的最小 vnode 数量。
    • write w - 在客户端被告知写入成功之前必须返回写入成功的最小 vnode 数
    • 主要读取 pr - 与 r 相同,但可能不考虑后备 vnode
    • 主要写入 pw - 与 w 相同,但可能不考虑后备 vnode

    rw quorums 的默认值为(n_val / 2) + 1,默认n_val=3 为2。

    发生了什么

    当您将值写入 2 节点集群时,每个值的 2 个副本被写入一个节点,1 个副本被写入另一个节点。哪个节点收到 2 个副本在预列表之间会有所不同。我预计除法大约是您编写的密钥的一半被写入节点 1 两次,一次写入节点 2,反之亦然。

    然后,当您停止节点 1 时,它的所有 vnode 同时变得不可用。您对节点 2 的第一个读取请求会导致它启动 1 或 2 个后备 vnode 以替换预列表中缺少的 vnode。这些回退在完成启动之前将无法响应,因此对 get 过程的第一个回复将来自节点 2 上的主 vnode,该 vnode 将具有该值。然后 get 进程将等待另一个回复(以满足默认的 r=2 quorum),这可能是来自新启动(并且非常空)的回退 vnode 的未找到,之后它将值返回给客户端。

    get 进程在回复后不会立即退出。它等待来自所有 vnode 的响应,如果它们不匹配,它会比较返回的值,根据它们的 vclock 选择最新的,并将解析的值发送回 vnode。该过程称为read repair,是恢复一致性的关键。

    随着每次连续读取,之前的读取已经需要所需的回退,因此已经开始。

    假设您将默认后端保留在 Bitcask,没有该值的后备 vnode 将扫描 RAM 中的密钥目录,发现请求的密钥不存在,并返回 notfound。拥有数据的 vnode 将扫描 keydir,找到所请求密钥的条目,并在包含数据的磁盘文件中找到具有引用和偏移量的条目,执行磁盘读取以获取数据,然后将其发送到 get 进程。您可以由此推断,一个 notfound 响应的生成速度比带有数据的响应快得多,因为不涉及磁盘访问。

    因此,如果以下所有条件都为真:

    • 您的读取请求所需的所有 vnode 都在运行
    • 自回退开始后未请求密钥
    • 密钥被两次写入节点 1,一次写入节点 2
    • 使用默认的 n_val=3 和 r=2

    然后get进程会先收到2个notfound响应,满足r=2的quorum,然后回复notfound给客户端。它还会在适当的时候收到带有数据的第三个响应,并将值写入回退 vnode。

    下一个读取请求将找到所有 3 个已填充的 vnode 并返回该值。

    如何预防

    为了防止这种情况发生:

    • 使用要求 preflist 中的所有 vnode 响应的仲裁 (r=all)
    • 使用需要来自主 vnode (pr=1) 答案的仲裁
    • 将节点添加到集群,直到没有 preflist 在同一节点上有 2 个成员。

    将节点加入集群时,在plan 阶段,如果任何节点包含预置列表的 2 个成员,您应该会看到“并非所有副本都位于不同节点上”的警告。

    将 vnode 分配给节点的算法使用target_n_val 设置,该设置通常高于 n_val,以确保如果节点发生故障,备用 vnode 的首选不是已经有另一个成员的节点预表。 target_n_val默认为4个,通常建议集群中有target_n_val + 1节点,保证vnode分配不重叠。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 2016-08-31
      相关资源
      最近更新 更多