暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

etcd源码剖析(五)-store总结

考拉苑 2018-09-01
350

前面四篇文章也算是差不过针对etcd的store涉及到的核心内容作了说明,今天主要是对前面提供的剖析源码进行一个总结

1 架构


etcd

从etcd的架构图中我们可以看到,etcd主要分为四个部分。

  • HTTP Server: 用于处理用户发送的API请求以及其它etcd节点的同步与心跳信息请求。

  • Store:用于处理etcd支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等等,是etcd对用户提供的大多数API功能的具体实现。

  • Raft:Raft强一致性算法的具体实现,是etcd的核心。

  • WAL:Write Ahead Log(预写式日志),是etcd的数据存储方式。除了在内存中存有所有数据的状态以及节点的索引以外,etcd就通过WAL进行持久化存储。WAL中,所有的数据提交前都会事先记录日志。Snapshot是为了防止数据过多而进行的状态快照;Entry表示存储的具体日志内容。

通常,一个用户的请求发送过来,会经由HTTP Server转发给Store进行具体的事务处理
如果涉及到节点的修改,则交给Raft模块进行状态的变更、日志的记录,然后再同步给别的etcd节点以确认数据提交
最后进行数据的提交,再次同步。

2 etcd概念词汇表

Raft:etcd所采用的保证分布式系统强一致性的算法。
Node:一个Raft状态机实例。
Member: 一个etcd实例。它管理着一个Node,并且可以为客户端请求提供服务。
Cluster:由多个Member构成可以协同工作的etcd集群。
Peer:对同一个etcd集群中另外一个Member的称呼。
Client: 向etcd集群发送HTTP请求的客户端。
WAL:预写式日志,etcd用于持久化存储的日志格式。
snapshot:etcd防止WAL文件过多而设置的快照,存储etcd数据状态。
Proxy:etcd的一种模式,为etcd集群提供反向代理服务。
Leader:Raft算法中通过竞选而产生的处理所有数据提交的节点。
Follower:竞选失败的节点作为Raft中的从属节点,为算法提供强一致性保证。
Candidate:当Follower超过一定时间接收不到Leader的心跳时转变为Candidate开始竞选。
Term:某个节点成为Leader到下一次竞选时间,称为一个Term。
Index:数据项编号。Raft中通过Term和Index来定位数据。

3 Store

Store这个模块顾名思义,就像一个商店把etcd已经准备好的各项底层支持加工起来,为用户提供五花八门的API支持,处理用户的各项请求。

要理解Store,只需要从etcd的API入手,接下来我们能够看到有如下API是对etcd存储的键值进行的操作,亦即Store提供的内容。

API中提到的目录(Directory)和键(Key),上文中也可能称为etcd节点(Node)。

  • 为etcd存储的键赋值

curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello world"{    "action": "set",    "node": {        "createdIndex": 2,        "key": "/message",        "modifiedIndex": 2,        "value": "Hello world"
    }
}

反馈的内容含义如下:

  1. action: 进行的动作名称。

  2. node.key: 请求的HTTP路径。etcd使用一个类似文件系统的方式来反映键值存储的内容。

  3. node.value: 请求的键所存储的内容。

  4. node.createdIndex: etcd节点每次有变化时都会自增的一个值,除了用户请求外,etcd内部运行(如启动、集群信息变化等)也会对节点有变动而引起这个值的变化。

node.modifiedIndex: 类似node.createdIndex,能引起modifiedIndex变化的操作包括set, delete, update, create, compareAndSwap and compareAndDelete。

  • 查询etcd某个键存储的值

curl http://127.0.0.1:2379/v2/keys/message
  • 修改键值:与创建新值几乎相同,但是反馈时会有一个prevNode
    值反应了修改前存储的内容。

curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello etcd"
  • 删除一个值

curl http://127.0.0.1:2379/v2/keys/message -XDELETE
  • 对一个键进行定时删除:etcd中对键进行定时删除,设定一个TTL值,当这个值到期时键就会被删除。反馈的内容会给出expiration项告知超时时间,ttl项告知设定的时长。

curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl=5
  • 取消定时删除任务

curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=true
  • 对键值修改进行监控:etcd提供的这个API让用户可以监控一个值或者递归式的监控一个目录及其子目录的值,当目录或值发生变化时,etcd会主动通知。

curl http://127.0.0.1:2379/v2/keys/foo?wait=true
  • 对过去的键值操作进行查询:类似上面提到的监控,只不过监控时加上了过去某次修改的索引编号,就可以查询历史操作。默认可查询的历史记录为1000条。

curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=7'
  • 自动在目录下创建有序键。在对创建的目录使用POST
    参数,会自动在该目录下创建一个以createdIndex值为键的值,这样就相当于以创建时间先后严格排序了。这个API对分布式队列这类场景非常有用。

curl http://127.0.0.1:2379/v2/keys/queue -XPOST -d value=Job1{    "action": "create",    "node": {        "createdIndex": 6,        "key": "/queue/6",        "modifiedIndex": 6,        "value": "Job1"
    }
}
  • 按顺序列出所有创建的有序键。

curl -s 'http://127.0.0.1:2379/v2/keys/queue?recursive=true&sorted=true'
  • 创建定时删除的目录:就跟定时删除某个键类似。如果目录因为超时被删除了,其下的所有内容也自动超时删除。

curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d ttl=30 -d dir=true
  • 刷新超时时间

curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d ttl=30 -d dir=true -d prevExist=true
  • 自动化CAS(Compare-and-Swap)操作:etcd强一致性最直观的表现就是这个API,通过设定条件,阻止节点二次创建或修改。即用户的指令被执行当且仅当CAS的条件成立。条件有以下几个。

    curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=one

    然后再进行操作:

    curl http://127.0.0.1:2379/v2/keys/foo?prevExist=false -XPUT -d value=three
    1. prevValue 先前节点的值,如果值与提供的值相同才允许操作。

    2. prevIndex 先前节点的编号,编号与提供的校验编号相同才允许操作。

    3. prevExist 先前节点是否存在。如果存在则不允许操作。这个常常被用于分布式锁的唯一获取。
      假设先进行了如下操作:设定了foo的值。

    就会返回创建失败的错误。

  • 条件删除(Compare-and-Delete):与CAS类似,条件成立后才能删除。

curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d dir=true
  • 创建目录

curl http://127.0.0.1:2379/v2/keys/
  • 列出目录下所有的节点信息,最后以/
    结尾。还可以通过recursive参数递归列出所有子目录信息。

curl http://127.0.0.1:2379/v2/keys/
  • 删除目录:默认情况下只允许删除空目录,如果要删除有内容的目录需要加上recursive=true
    参数。

curl 'http://127.0.0.1:2379/v2/keys/foo_dir?dir=true' -XDELETE
  • 创建一个隐藏节点:命名时名字以下划线_
    开头默认就是隐藏键。

curl http://127.0.0.1:2379/v2/keys/_message -XPUT -d value="Hello hidden world"

基本上述这些API的使用,基本上对Store的工作内容基本了解了。

它对etcd下存储的数据进行加工,创建出如文件系统般的树状结构供用户快速查询。

它有一个Watcher
用于节点变更的实时反馈,还需要维护一个WatcherHub
对所有Watcher
订阅者进行通知的推送。

同时,它还维护了一个由定时键构成的小顶堆,快速返回下一个要超时的键。

最后,所有这些API的请求都以事件的形式存储在事件队列中等待处理。

关于watch【关于这部分先简单介绍下,后面会有专门的文章介绍】

先上个简单的watch流程吧



watch


etcd会保存每个客户端发来的watch请求,watch请求可以关注一个key(单key),或者一个key前缀(区间)。

etcd会有一个协程持续不断的遍历所有的watch请求,每个watch对象都维护了其watch的key事件推送到了哪个revision。


文章转载自考拉苑,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论