Redis 集群¶
https://blueprints.launchpad.net/trove/+spec/redis-cluster
Redis 是一种 NoSQL 数据库,专为高性能缓存和键/值数据持久化而设计。本文档概述了为 Redis 实现集群的提案。
问题描述¶
为 Redis 实现集群。
提议的变更¶
Redis 集群功能将努力实现用户在 Trove 环境中实现 Redis 集群所需的最低功能。虽然 Trove 将提供功能以支持无法直接通过 Redis API 实现的操作,但尽可能将功能留给用户通过 Redis API 执行。做出此决定的原因是,通过 Web 界面提供所有必需的功能将非常困难,并且 Redis 用户将熟悉 Redis 命令集。
配置¶
以下配置值将在 Redis 配置组中实现
cfg.BoolOpt('cluster_support', default=True,
help='Enable clusters to be created and managed.'),
cfg.StrOpt('api_strategy',
default='trove.common.strategies.cluster.experimental.'
'redis.api.RedisAPIStrategy',
help='Class that implements datastore-specific API logic.'),
cfg.StrOpt('taskmanager_strategy',
default='trove.common.strategies.cluster.experimental.redis.'
'taskmanager.RedisTaskManagerStrategy',
help='Class that implements datastore-specific task manager '
'logic.'),
cfg.StrOpt('guestagent_strategy',
default='trove.common.strategies.cluster.experimental.'
'redis.guestagent.RedisGuestAgentStrategy',
help='Class that implements datastore-specific Guest Agent API '
'logic.'),
数据库¶
没有更改。
REST API¶
创建集群¶
cluster-create 命令将允许用户使用指定的 master 节点数量创建集群。数据槽将均匀地分配到创建的节点之间。
请求
POST /v1.0/<tenant_id>/clusters
{
"cluster": {
"name": "redis-clstr",
"datastore": {
"type": "redis",
"version": "3.0"
},
"instances": [
{
"flavorRef": "2",
"volume": {
"size": 2
}
},
{
"flavorRef": "2",
"volume": {
"size": 2
}
},
{
"flavorRef": "2",
"volume": {
"size": 2
}
},
{
"flavorRef": "2",
"volume": {
"size": 2
}
},
]
}
}
响应
{
"cluster": {
"id": "edaac9ca-b5e1-4028-adb7-fa7653e11224",
"task": {
"id": 2,
"name": "BUILDING",
"description": "Building the initial cluster."
},
"name": "redis-clstr",
"created": "2015-01-29T20:19:23",
"updated": "2015-01-29T20:19:23",
"links": [{...}],
"datastore": {
"type": "redis",
"version": "3.0"
},
"ip": [],
"instances": [
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"name": "redis-clstr-member-1",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
{
"id": "965ef811-7c1d-47fc-89f2-a89dfdd23ef2",
"name": "redis-clstr-member-2",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
{
"id": "3642f41c-e8ad-4164-a089-3891bf7f2d2b",
"name": "redis-clstr-member-3",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"name": "redis-clstr-member-4",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
]
}
}
HTTP 状态码
202 - Accepted.
400 - BadRequest. Server could not understand request.
403 - Forbidden. Local storage not specified in flavor ID: <ID>.
403 - Forbidden. A flavor is required for each instance in the cluster.
404 - Not Found. Flavor not found.
扩展集群¶
向集群添加节点。添加的节点将是空的 master 节点,并且不会分配任何槽位给它们。
请求
POST /v1.0/<tenant_id>/clusters/edaac9ca-b5e1-4028-adb7-fa7653e11224/action
{
"grow": [
{
"flavorRef": "2",
"volume": {
"size": 2
}
},
{
"flavorRef": "2",
"volume": {
"size": 2
}
}
]
}
响应
{
"cluster": {
"id": "edaac9ca-b5e1-4028-adb7-fa7653e11224",
"task": {
"id": 2,
"name": "BUILDING",
"description": "Building the initial cluster."
},
"name": "redis-clstr",
"created": "2015-01-29T20:19:23",
"updated": "2015-01-29T20:19:23",
"links": [{...}],
"datastore": {
"type": "redis",
"version": "3.0"
},
"ip": [],
"instances": [
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"name": "redis-clstr-member-5",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
{
"id": "965ef811-7c1d-47fc-89f2-a89dfdd23ef2",
"name": "redis-clstr-member-6",
"status": "BUILD",
"ip": [],
"links": [{...}],
"flavor": {
"id": "2",
"links": [{...}]
},
"volume": {
"size": 2
}
},
]
}
}
HTTP 状态码
202 - Accepted.
400 - BadRequest. Server could not understand request.
403 - Forbidden. Local storage not specified in flavor ID: <ID>.
403 - Forbidden. A flavor is required for each instance in the cluster.
404 - Not Found. Flavor not found.
缩减集群¶
从集群中删除指定的节点。预计所有数据槽都已从节点中删除 - 否则 shrink 操作将失败。
请求
POST /v1.0/<tenant_id>/clusters/<cluster_id>/action
"shrink": [
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
},
{
"id": "965ef811-7c1d-47fc-89f2-a89dfdd23ef2",
}
]
}
响应
N/A
HTTP 代码
202 - Accepted.
403 - Forbidden. One or more nodes have data slots assigned.
404 - Not found. Instance <id> does not exist.
显示集群¶
请求
GET /v1.0/<tenant_id>/clusters/edaac9ca-b5e1-4028-adb7-fa7653e11224
响应
{
"cluster": {
"id": "edaac9ca-b5e1-4028-adb7-fa7653e11224",
"task": {
"id": 1,
"name": "NONE",
"description": "No tasks for the cluster."
},
"name": "redis-clstr",
"created": "2015-01-29T20:19:23",
"updated": "2015-01-29T20:19:23",
"links": [{...}],
"datastore": {
"type": "redis",
"version": "3.0"
},
"ip": ["10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4",],
"instances": [
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"name": "redis-clstr-member-1",
"status": "ACTIVE",
"ip": ["10.0.0.1"],
"links": [{...}],
"flavor": {
"id": "7",
"links": [{...}]
},
"volume": {
"size": 2
},
}
{
"id": "965ef811-7c1d-47fc-89f2-a89dfdd23ef2",
"name": "redis-clstr-member-2",
"status": "ACTIVE",
"links": [{...}],
"flavor": {
"ip": ["10.0.0.2"],
"id": "7",
"links": [{...}]
},
"volume": {
"size": 2
},
},
{
"id": "3642f41c-e8ad-4164-a089-3891bf7f2d2b",
"name": "redis-clstr-member-3",
"status": "BUILD",
"ip": ["10.0.0.3"],
"links": [{...}],
"flavor": {
"id": "7",
"links": [{...}]
},
"volume": {
"size": 2
},
},
{
"id": "3642f41c-e8ad-4164-a089-3891bf7f2d2b",
"name": "redis-clstr-member-4",
"status": "BUILD",
"ip": ["10.0.0.4"],
"links": [{...}],
"flavor": {
"id": "7",
"links": [{...}]
},
"volume": {
"size": 2
},
}
]
}
}
HTTP 状态码
200 - OK.
404 - Not Found. Cluster not found.
显示实例¶
请求
GET /v1.0/<tenant_id>/clusters/edaac9ca-b5e1-4028-adb7-fa7653e11224/instances/416b0b16-ba55-4302-bbd3-ff566032e1c1
响应
{
"instance": {
"status": "ACTIVE",
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"cluster_id": "edaac9ca-b5e1-4028-adb7-fa7653e11224",
"name": "redis-clstr-member-1",
"created": "2015-01-29T20:19:23",
"updated": "2015-01-29T20:19:23",
"links": [{...}],
"datastore": {
"type": "redis",
"version": "3.0"
},
"ip": ["10.0.0.1"],
"flavor": {
"id": "7",
"links": [{...}],
},
"volume": {
"size": 2,
"used": 0.17
}
}
}
HTTP 状态码
200 - OK.
404 - Not Found. Cluster not found.
404 - Not Found. Instance not found.
列出集群¶
请求
GET /v1.0/<tenant_id>/clusters
响应
{
"clusters": [
{
"id": "edaac9ca-b5e1-4028-adb7-fa7653e11224",
"task": {
"id": 1,
"name": "NONE",
"description": "No tasks for the cluster."
},
"name": "redis-clstr",
"created": "2015-01-29T20:19:23",
"updated": "2015-01-29T20:19:23",
"links": [{...}],
"datastore": {
"type": "redis",
"version": "3.0"
},
"instances": [
{
"id": "416b0b16-ba55-4302-bbd3-ff566032e1c1",
"name": "redis-clstr-member-1",
"links": [{...}],
}
{
"id": "965ef811-7c1d-47fc-89f2-a89dfdd23ef2",
"name": "redis-clstr-member-2",
"links": [{...}],
},
{
"id": "3642f41c-e8ad-4164-a089-3891bf7f2d2b",
"name": "redis-clstr-member-3",
"links": [{...}],
},
{
"id": "3642f41c-e8ad-4164-a089-3891bf7f2d2b",
"name": "redis-clstr-member-4",
"links": [{...}],
}
]
},
...
]
}
HTTP 状态码
200 - OK.
删除集群¶
请求
DELETE /v1.0/<tenant_id>/clusters/<cluster_id>
响应
N/A
HTTP 代码
202 - Accepted.
404 - Not found
公共 API¶
没有公共 API 变更。
公共 API 安全¶
n/a
Python API¶
无 Python API 更改。
CLI (python-troveclient)¶
无 CLI 更改。
内部 API¶
预计不会对 guestagent api 进行任何更改,除了实现现有的 API 方法。
Guest Agent¶
以下方法将在 RedisGuestAgentAPI 中实现
def get_node_ip(self):
LOG.debug("Retrieve ip info from node.")
return self._call("get_node_ip",
guest_api.AGENT_HIGH_TIMEOUT, self.version_cap)
def get_node_id_for_removal(self):
LOG.debug("Validating cluster node removal.")
return self._call("get_node_id_for_removal",
guest_api.AGENT_HIGH_TIMEOUT, self.version_cap)
def remove_nodes(self, node_ids):
LOG.debug("Removing nodes from cluster.")
return self._call("remove_nodes", guest_api.AGENT_HIGH_TIMEOUT,
self.version_cap, node_ids=node_ids)
def cluster_meet(self, ip, port):
LOG.debug("Joining node to cluster.")
return self._call("cluster_meet", guest_api.AGENT_HIGH_TIMEOUT,
self.version_cap, ip=ip, port=port)
def cluster_addslots(self, first_slot, last_slot):
LOG.debug("Adding slots %s-%s to cluster.", first_slot, last_slot)
return self._call("cluster_addslots",
guest_api.AGENT_HIGH_TIMEOUT, self.version_cap,
first_slot=first_slot, last_slot=last_slot)
def cluster_complete(self):
LOG.debug("Notifying cluster install completion.")
return self._call("cluster_complete", guest_api.AGENT_HIGH_TIMEOUT,
self.version_cap)
备选方案¶
n/a
实现¶
负责人¶
- 主要负责人
vgnbkr
里程碑¶
- 完成目标里程碑
Liberty-3
工作项¶
为 Redis 实现集群
为 Redis 实现新的 Taskmanager 集群策略,实现 python API 和 shell 用于 shrink/grow(这可能已经通过 cluster-scaling bp 实现完成),如果缺少缩放实现,则将 grow/shrink 添加到集群策略中,实现 guest agent 支持加入/离开集群,根据需要实现单元测试,如果那时已经确定了执行此操作的机制,则实现集成测试
升级影响¶
由于这是一个新的实现,因此预计不会产生升级影响。
依赖项¶
此功能依赖于 https://blueprints.launchpad.net/trove/+spec/cluster-scaling 中概述的集群缩放功能
测试¶
MongoDB 和 Cassandra 的集群集成测试仍在进行中。预计 Redis 将实现/运行类似的集成测试。
文档影响¶
需要更新 Redis 的数据存储文档以反映集群支持。