Redis 是一个高性能的 key-value 存储系统,被广泛用于微服务架构中。如果我们想要使用 Redis 集群模式提供的高级特性,则需要对客户端代码进行改动,这带来了应用升级和维护的一些困难。利用 Istio 和 Envoy ,我们可以在不修改客户端代码的前提下实现客户端无感知的 Redis Cluster 数据分片,并提供读写分离、流量镜像等高级流量管理功能。

Redis Cluster

Redis 的一个常见用途是用作数据高速缓存。通过在应用服务器和数据库服务器之间加入一个 Redis 缓存层,可以减少应用服务器对数据库的大量读操作,避免数据库服务器在大压力下响应缓慢甚至宕机的风险,显著加强整个系统的健壮性。Redis 作为数据缓存的原理如图所示:

在一个小规模的系统中,上图所示的单个 Redis 就可以很好地实现缓存层的功能。当系统中需要缓存的数据量较大时,一个 Redis 服务器无法承担所有应用服务器的缓存需求;同时单个 Redis 实例失效时也会导致大量读请求被直接发送到后端的数据库服务器上,导致数据库服务器瞬时压力超标,影响系统的稳定性。我们可以采用 Redis Cluster 来对缓存数据进行分片,将不同的数据放到不同的 Redis 分片中,以提高 Redis 缓存层的容量能力。在每个 Redis 分片中,还可以采用多个 replica 节点对缓存的读请求进行负载分担,并实现 Redis 的高可用。采用了 Redis Cluster 的系统如下图所示:

从图中可以看到,在 Redis Cluster 模式下,客户端需要根据集群的分片规则将不同 key 的读写操作发送到集群中不同的 Redis 节点上,因此客户端需要了解 Redis Cluster 的拓扑结构,这导致我们无法在不修改客户端的情况下将一个使用 Redis 独立节点模式的应用平滑迁移到 Redis Cluster 上。另外,由于客户端需要了解 Redis Cluster 的内部拓扑,也将导致客户端代码和 Redis Cluster 运维上的耦合,例如要实现读写分离或者流量镜像的话,就需要修改每个客户端的代码并重新部署。

这种场景下,我们可以在应用服务器和 Redis Cluster 之间放置一个 Envoy 代理服务器,由 Envoy 来负责将应用发出的缓存读写请求路由到正确的 Redis 节点上。一个微服务系统中存在大量需要访问缓存服务器的应用进程,为了避免单点故障和性能瓶颈,我们以 Sidecar 的形式为每个应用进程部署一个 Envoy 代理。同时,为了简化对这些代理的管理工作,我们可以采用 Istio 作为控制面来统一对所有 Envoy 代理进行配置,如下图所示:

在本文的后续部分,我们将介绍如何通过 Istio 和 Envoy 来管理 Redis Cluster,实现客户端无感知的数据分区,以及读写分离、流量镜像等高级路由策略。

部署 Istio

Pilot 中已经支持了 Redis 协议,但功能较弱,只能为 Redis 代理配置一个缺省路由,而且不支持 Redis Cluster 模式,无法实现 Redis filter 的数据分片、读写分离、流量镜像等高级流量管理功能。为了让 Istio 可以将 Redis Cluster 相关的配置下发到 Envoy Sidecar 上,我们修改了 EnvoyFilter 配置相关代码,以支持 EnvoyFilter 的 "REPLCAE" 操作。该修改的 PR Implement REPLACE operation for EnvoyFilter patch 已经提交到 Istio 社区,并合入到了主分支中,将在 Istio 后续的版本中发布。

在撰写本文的时候,最新的 Istio 发布版本 1.7.3 中尚未合入该 PR。因此我构建了一个 Pilot 镜像,以启用 EnvoyFilter 的 "REPLACE" 操作。在安装 Istio 时,我们需要在 istioctl 命令中指定采用该 Pilot 镜像,如下面的命令行所示:

$ cd istio-1.7.3/bin
$ ./istioctl install --set components.pilot.hub=zhaohuabing --set components.pilot.tag=1.7.3-enable-ef-replace

备注:如果你采用的 Istio 版本新于 1.7.3,并且已经合入了该 PR,则可以直接采用 Istio 版本中缺省的 Pilot 镜像。

部署 Redis Cluster

请从 https://github.com/zhaohuabing/istio-redis-culster 下载下面示例中需要用到的相关代码:

$ git clone https://github.com/zhaohuabing/istio-redis-culster.git
$ cd istio-redis-culster

我们创建一个 "redis" namespace 来部署本例中的 Redis Cluster。

$ kubectl create ns redis
namespace/redis created

部署 Redis 服务器的 Statefulset 和 Configmap。

$ kubectl apply -f k8s/redis-cluster.yaml -n redis
configmap/redis-cluster created
statefulset.apps/redis-cluster created
service/redis-cluster created

验证 Redis 部署

确认 Redis 节点已经启动并正常运行:

$ kubectl get pod -n redis
NAME READY STATUS RESTARTS AGE
redis-cluster-0 2/2 Running 0 4m25s
redis-cluster-1 2/2 Running 0 3m56s
redis-cluster-2 2/2 Running 0 3m28s
redis-cluster-3 2/2 Running 0 2m58s
redis-cluster-4 2/2 Running 0 2m27s
redis-cluster-5 2/2 Running 0 117s

创建 Redis Cluster

在上面的步骤中,我们采用 Statefulset 部署了6个 Redis 节点,但目前这6个节点还是相互独立的,并未形成一个集群。下面我们采用 Redis 的 cluster create 命令将这些节点组成一个 Redis Cluster。

$ kubectl exec -it redis-cluster-0 -n redis -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 ' -n redis)
Defaulting container name to redis.
Use 'kubectl describe pod/redis-cluster-0 -n redis' to see all of the containers in this pod.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.16.0.72:6379 to 172.16.0.138:6379
Adding replica 172.16.0.201:6379 to 172.16.1.52:6379
Adding replica 172.16.0.139:6379 to 172.16.1.53:6379
M: 8fdc7aa28a6217b049a2265b87bff9723f202af0 172.16.0.138:6379
slots:[0-5460] (5461 slots) master
M: 4dd6c1fecbbe4527e7d0de61b655e8b74b411e4c 172.16.1.52:6379
slots:[5461-10922] (5462 slots) master
M: 0b86a0fbe76cdd4b48434b616b759936ca99d71c 172.16.1.53:6379
slots:[10923-16383] (5461 slots) master
S: 94b139d247e9274b553c82fbbc6897bfd6d7f693 172.16.0.139:6379
replicates 0b86a0fbe76cdd4b48434b616b759936ca99d71c
S: e293d25881c3cf6db86034cd9c26a1af29bc585a 172.16.0.72:6379
replicates 8fdc7aa28a6217b049a2265b87bff9723f202af0
S: ab897de0eca1376558e006c5b0a49f5004252eb6 172.16.0.201:6379
replicates 4dd6c1fecbbe4527e7d0de61b655e8b74b411e4c
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 172.16.0.138:6379)
M: 8fdc7aa28a6217b049a2265b87bff9723f202af0 172.16.0.138:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 4dd6c1fecbbe4527e7d0de61b655e8b74b411e4c 172.16.1.52:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 94b139d247e9274b553c82fbbc6897bfd6d7f693 172.16.0.139:6379
slots: (0 slots) slave
replicates 0b86a0fbe76cdd4b48434b616b759936ca99d71c
M: 0b86a0fbe76cdd4b48434b616b759936ca99d71c 172.16.1.53:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: ab897de0eca1376558e006c5b0a49f5004252eb6 172.16.0.201:6379
slots: (0 slots) slave
replicates 4dd6c1fecbbe4527e7d0de61b655e8b74b411e4c
S: e293d25881c3cf6db86034cd9c26a1af29bc585a 172.16.0.72:6379
slots: (0 slots) slave
replicates 8fdc7aa28a6217b049a2265b87bff9723f202af0
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

验证 Redis Cluster

我们可以采用 cluster info 命令查看 Redis Cluster 的配置信息和 Cluster 中的成员节点,以验证集群是否创建成功。

$ kubectl exec -it redis-cluster-0 -c redis -n redis -- redis-cli cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:206
cluster_stats_messages_pong_sent:210
cluster_stats_messages_sent:416
cluster_stats_messages_ping_received:205
cluster_stats_messages_pong_received:206
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:416

部署测试用客户端

我们部署一个客户端,以用于发送测试命令:

$ kubectl apply -f k8s/redis-client.yaml -n redis
deployment.apps/redis-client created

通过 Istio 下发 Redis Cluster 相关的 Envoy 配置

在下面的步骤中,我们将通过 Istio 向 Envoy Sidecar 下发 Redis Cluster 相关配置,以在无需改动客户端的情况下启用 Redis Cluster 的高级功能,包括数据分片、读写分离和流量镜像。

创建 Envoy Redis Cluster

Envoy 提供了 "envoy.clusters.redis" 类型的 Envoy Cluster 来连接后端的 Redis Cluster,Envoy 会通过该 Cluster 获取后端 Redis Cluster 的拓扑结构,包括有多少个分片(shard),每个分片负责哪些 slot,以及分片中包含哪些节点,以将来自客户端的请求分发到正确的 Redis 节点上。

采用 EnvoyFilter 来创建所需的 Envoy Redis Cluster:

$ kubectl apply -f istio/envoyfilter-custom-redis-cluster.yaml
envoyfilter.networking.istio.io/custom-redis-cluster created

创建 Envoy Redis Proxy

Istio 缺省下发的 LDS 中配置的是 TCP proxy filter,我们需要将其替换为 Redis Proxy filter。

由于 1.7.3 中尚不支持 EnvoyFilter 的 "REPLACE" 操作,我们首先需要更新 EnvoyFilter 的 CRD 定义,然后才能创建该 EnvoyFilter:

$ kubectl apply -f istio/envoyfilter-crd.yaml
customresourcedefinition.apiextensions.k8s.io/envoyfilters.networking.istio.io configured

采用 EnvoyFilter 来将 TCP proxy filter 替换为 Redis Proxy filter,以使 Envoy 可以代理来自客户端的 Redis 操作请求:

$ sed -i .bak "s/\${REDIS_VIP}/`kubectl get svc redis-cluster -n redis -o=jsonpath='{.spec.clusterIP}'`/" istio/envoyfilter-redis-proxy.yaml
$ kubectl apply -f istio/envoyfilter-redis-proxy.yaml
envoyfilter.networking.istio.io/add-redis-proxy created

验证 Redis Cluster 功能

现在一切就绪,下面我们来验证 Redis Cluster 的各项功能。

Redis 数据分片

我们通过 Istio 将 EnvoyFilter 中定义的配置下发到 Envoy 后,Envoy 就能够自动发现后端 Redis Cluster 的拓扑结构,并根据客户端请求中的 key 将请求自动分发到 Redis Cluster 中正确的节点上。

根据前面创建 Redis Cluster 步骤中的命令行输出,我们可以看出该 Redis Cluster 的拓扑结构:Cluster 中有三个分片,每个分片中有一个 Master 节点,一个 Slave(Replica) 节点。客户端通过和其部署在同一个 Pod 中的 Envoy Proxy 访问 Redis Cluster,如下图所示:

Redis Cluster 中各个分片的 Master 和 Slave 节点地址:

Shard[0] Master[0]  redis-cluster-0 172.16.0.138:6379   replica  redis-cluster-4 172.16.0.72:6379  -> Slots 0 - 5460
Shard[1] Master[1] redis-cluster-1 172.16.1.52:6379 replica redis-cluster-5 172.16.0.201:6379 -> Slots 5461 - 10922
Shard[2] Master[2] redis-cluster-2 172.16.1.53:6379 replica redis-cluster-3 172.16.0.139:6379 -> Slots 10923 - 16383

备注:如果你在自己的 K8s cluster 中部署该示例,那么 Redis Cluster 中各个节点的 IP 地址和拓扑结构可能稍有不同,但基本结构应该是类似的。

我们尝试从客户端向 Rdeis Cluster 发送一些不同 key 的 set 请求:

$ kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster
redis-cluster:6379> set a a
OK
redis-cluster:6379> set b b
OK
redis-cluster:6379> set c c
OK
redis-cluster:6379> set d d
OK
redis-cluster:6379> set e e
OK
redis-cluster:6379> set f f
OK
redis-cluster:6379> set g g
OK
redis-cluster:6379> set h h
OK

从客户端来看,所有的请求都成功了,我们可以使用 scan 命令在服务器端查看各个节点中的数据:

查看分片 Shard[0] 中的数据,master 节点是 redis-cluster-0 slave 节点是 redis-cluster-4。

$ kubectl exec redis-cluster-0 -c redis -n redis -- redis-cli --scan
b
f
$ kubectl exec redis-cluster-4 -c redis -n redis -- redis-cli --scan
f
b

查看分片 Shard[1] 中的数据,master 节点是 redis-cluster-1 slave 节点是 redis-cluster-5。

$ kubectl exec redis-cluster-1 -c redis -n redis -- redis-cli --scan
c
g
$ kubectl exec redis-cluster-5 -c redis -n redis -- redis-cli --scan
g
c

查看分片 Shard[2] 中的数据,master 节点是 redis-cluster-2 slave 节点是 redis-cluster-3。

$ kubectl exec redis-cluster-2 -c redis -n redis -- redis-cli --scan
a
e
d
h
$ kubectl exec redis-cluster-3 -c redis -n redis -- redis-cli --scan
h
e
d
a

从上面的验证结果中可以看到,客户端设置的数据被分发到了 Redis Cluster 中的三个分片中。该数据分发过程是由 Envoy Redis Proxy 自动实现的,客户端并不感知后端的 Redis Cluster,对客户端而言,和该 Redis Cluster 的交互与和一个单一 Redis 节点的交互是相同的。

采用该方法,我们可以在应用业务规模逐渐扩张,单一 Redis 节点压力过大时,将系统中的 Redis 从单节点无缝迁移到集群模式。在集群模式下,不同 key 的数据被缓存在不同的数据分片中,我们可以增加分片中 Replica 节点的数量来对一个分片进行扩容,也可以增加分片个数来对整个集群进行扩展,以应对由于业务不断扩展而增加的数据压力。由于 Envoy 可以感知 Redis Cluster 集群拓扑,数据的分发由 Envoy 完成,整个迁移和扩容过程无需客户端,不会影响到线上业务的正常运行。

Redis 读写分离

在一个 Redis 分片中,通常有一个 Master 节点,一到多个 Slave(Replica)节点,Master 节点负责写操作,并将数据变化同步到 Slave 节点。当来自应用的读操作压力较大时,我们可以在分片中增加更多的 Replica,以对读操作进行负载分担。Envoy Redis Rroxy 支持设置不同的读策略:

  • MASTER: 只从 Master 节点读取数据,当客户端要求数据强一致性时需要采用该模式。该模式对 Master 压力较大,在同一个分片内无法采用多个节点对读操作进行负载分担。
  • PREFER_MASTER: 优先从 Master 节点读取数据,当 Master 节点不可用时,从 Replica 节点读取。
  • REPLICA: 只从 Replica 节点读取数据,由于 Master 到 Replica 的数据复制过程是异步执行的,采用该方式有可能读取到过期的数据,因此适用于客户端对数据一致性要求不高的场景。该模式下可以采用多个 Replica 节点来分担来自客户端的读负载。
  • PREFER_REPLICA: 优先从 Replica 节点读取数据,当 Replica 节点不可用时,从 Master 节点读取。
  • ANY: 从任意节点读取数据。

在前面下发的 EnvoyFilter 中,我们将 Envoy Redis Proxy 的读策略设置为了 "REPLICA", 因此客户端的读操作应该只会被发送到 Replica 节点。让我们使用下面的命令来验证读写分离的策略:

通过客户端发起一系列 key 为 "b" 的 getset 操作:

$ kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster

redis-cluster:6379> get b
"b"
redis-cluster:6379> get b
"b"
redis-cluster:6379> get b
"b"
redis-cluster:6379> set b bb
OK
redis-cluster:6379> get b
"bb"
redis-cluster:6379>

在前面的 Redis Cluster 拓扑中,我们已经得知 key "b" 属于 Shard[0] 这个分片。我们可以通过命令 redis-cli monitor 查看该分片中 Master 和 Replica 节点中收到的命令。

Master 节点:

$ kubectl exec redis-cluster-0 -c redis -n redis -- redis-cli monitor

Slave 节点:

$ kubectl exec redis-cluster-4 -c redis -n redis -- redis-cli monitor

从下图中可以看到,所有 get 请求都被 Envoy 发送到了 Replica 节点上。

Redis 流量镜像

Envoy Redis Proxy 支持流量镜像,即将客户端发送的请求同时发送到一个镜像 Redis 服务器/集群上。流量镜像是一个非常有用的功能,我们可以使用流量镜像将生产环境中的线上数据导入到测试环境中,以使用线上数据对应用进行尽可能真实的模拟测试,同时又不会影响到线上用户的正常使用。

我们创建一个单节点的 Redis 节点,用做镜像服务器:

$ kubectl apply -f k8s/redis-mirror.yaml -n redis
deployment.apps/redis-mirror created
service/redis-mirror created

采用 EnvoFilter 来启用镜像策略:

$ sed -i .bak "s/\${REDIS_VIP}/`kubectl get svc redis-cluster -n redis -o=jsonpath='{.spec.clusterIP}'`/" istio/envoyfilter-redis-proxy-with-mirror.yaml
$ kubectl apply -f istio/envoyfilter-redis-proxy-with-mirror.yaml
envoyfilter.networking.istio.io/add-redis-proxy configured

通过客户端发起一系列 key 为 "b" 的 getset 操作:

$ kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster
redis-cluster:6379> get b
"b"
redis-cluster:6379> get b
"b"
redis-cluster:6379> get b
"b"
redis-cluster:6379> set b bb
OK
redis-cluster:6379> get b
"bb"
redis-cluster:6379> set b bbb
OK
redis-cluster:6379> get b
"bbb"
redis-cluster:6379> get b
"bbb"

可以通过命令 redis-cli monitor 分别查看 Master、Replica 和镜像节点中收到的命令。

Master 节点:

$ kubectl exec redis-cluster-0 -c redis -n redis -- redis-cli monitor

Slave 节点:

$ kubectl exec redis-cluster-4 -c redis -n redis -- redis-cli monitor

镜像 节点:

$ kubectl exec -it `kubectl get pod -l app=redis-mirror -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-mirror -n redis -- redis-cli monitor

从下图中可以看到,所有 set 请求都被 Envoy 发送到了一份镜像节点上。

实现原理

在上面的步骤中,我们在 Istio 中创建了两个 EnvoyFilter 配置对象。这两个 EnvoyFilter 修改了 Envoy 代理的配置,主要包括两部分内容:Redis Proxy Network Filter 配置和 Redis Cluster 配置。

下面的 EnvoyFilter 替换了 Pilot 为 Redis Service 创建的 Listener 中的 TCP Proxy Network Filter,将其替换为一个 "type.googleapis.com/envoy.config.filter.network.redis_proxy.v2.RedisProxy" 类型的 Network Filter。 该 Redis Proxy 的缺省路由指向 "custom-redis-cluster",并且配置了读写分离策略和流量镜像策略。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: add-redis-proxy
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
listener:
name: ${REDIS_VIP}_6379 # Replace REDIS_VIP with the cluster IP of "redis-cluster service
filterChain:
filter:
name: "envoy.filters.network.tcp_proxy"
patch:
operation: REPLACE
value:
name: envoy.redis_proxy
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.redis_proxy.v2.RedisProxy
stat_prefix: redis_stats
prefix_routes:
catch_all_route:
request_mirror_policy: # Send requests to the mirror cluster
- cluster: outbound|6379||redis-mirror.redis.svc.cluster.local
exclude_read_commands: True # Mirror write commands only:
cluster: custom-redis-cluster
settings:
op_timeout: 5s
enable_redirection: true
enable_command_stats: true
read_policy: REPLICA # Send read requests to replica

下面的 EnvoyFilter 在 Pilot 下发的 CDS 中创建了一个 "envoy.clusters.redis" 类型的 Cluster: "custom-redis-cluster",该 Cluster 会采用 CLUSTER SLOTS 命令 向 Redis 集群中的一个随机节点查询集群的拓扑结构,并在本地保存该拓扑结构,以将来自客户端的请求分发到集群中正确的 Redis 节点上。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-redis-cluster
namespace: istio-system
spec:
configPatches:
- applyTo: CLUSTER
patch:
operation: INSERT_FIRST
value:
name: "custom-redis-cluster"
connect_timeout: 0.5s
lb_policy: CLUSTER_PROVIDED
load_assignment:
cluster_name: custom-redis-cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: redis-cluster-0.redis-cluster.redis.svc.cluster.local
port_value: 6379
- endpoint:
address:
socket_address:
address: redis-cluster-1.redis-cluster.redis.svc.cluster.local
port_value: 6379
- endpoint:
address:
socket_address:
address: redis-cluster-2.redis-cluster.redis.svc.cluster.local
port_value: 6379
- endpoint:
address:
socket_address:
address: redis-cluster-3.redis-cluster.redis.svc.cluster.local
port_value: 6379
- endpoint:
address:
socket_address:
address: redis-cluster-4.redis-cluster.redis.svc.cluster.local
port_value: 6379
- endpoint:
address:
socket_address:
address: redis-cluster-5.redis-cluster.redis.svc.cluster.local
port_value: 6379
cluster_type:
name: envoy.clusters.redis
typed_config:
"@type": type.googleapis.com/google.protobuf.Struct
value:
cluster_refresh_rate: 5s
cluster_refresh_timeout: 3s
redirect_refresh_interval: 5s
redirect_refresh_threshold: 5

小结

本文介绍了如何使用 Envoy 为微服务应用提供客户端无感知的 Redis 数据分片,以及如何通过 Istio 来统一管理系统中多个 Envoy 代理的 Redis Cluster 配置。我们可以看到,采用 Istio 和 Envoy 可以大大简化客户端使用 Redis Cluster 的编码和配置工作,并且可以在线修改 Redis Cluster 的运维策略,实现读写分离、流量镜像等高级流量管理。当然,引入 Istio 和 Envoy 并未减少整个系统的复杂度,而是将 Redis Cluster 维护的工作从各个分散的应用代码中集中到了服务网格基础设施层。对应广大应用开放者来说,其业务价值主要来自于应用代码,将大量精力投入此类基础设施是不太划算的。建议直接采用腾讯云上的云原生 Service Mesh 服务 TCM(Tencent Cloud Mesh),为微服务应用快速引入 Service Mesh 的流量管理和服务治理能力,而无需再关注 Service Mesh 基础设施自身的安装、维护、升级等事项。

参考文档

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

在 Istio 中实现 Redis 集群的数据分片、读写分离和流量镜像的更多相关文章

  1. Centos下Redis集群的搭建实现读写分离

    Centos下Redis一主多从架构搭建 搭建目标:因为自己笔记本电脑配置较低的原因,模拟两台机器之间搭建一主一从的架构,主节点Redis主要用来写数据,数据写入到主节点的Redis,然后从节点就可以 ...

  2. 在 Kubernetes 中部署 Redis 集群

    在 Kubernetes 中部署 Redis 集群 在Kubernetes中部署Redis集群面临挑战,因为每个 Redis 实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色.为此,我们需 ...

  3. 从零开始学习docker之在docker中搭建redis(集群)

    docker搭建redis集群 docker-compose是以多容器的方式启动,非常适合用来启动集群 一.环境准备 云环境:CentOS 7.6 64位 二.安装docker-compose #需要 ...

  4. maven项目中使用redis集群报错: java.lang.NumberFormatException: For input string: "7001@17001"

    解决:由于redis集群的采用的版本是2.7的,在maven的pom.xml中将jedis的版本改成2.9的就可以了

  5. maven项目中使用redis集群报错: java.lang.NumberFormatException: For input string: "7006@17006"

    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [redis.client ...

  6. Redis笔记 -- 在 Centos7.4单机中部署Redis集群(二)

    0x00--背景和目的 在单台PC服务器上部署Redis集群,通过不同的TCP端口启动多实例,模拟多台独立PC组成集群. 0x01--环境描述: Centos版本:CentOS Linux relea ...

  7. 用redis-dump工具对redis集群所有数据进行导出导入

    安装redis-dump redis-dump是基于ruby开发,需要ruby环境,而且新版本的redis-dump要求2.2.2以上的ruby版本,centos中yum只能安装2.0版本的ruby. ...

  8. mycat数据库集群系列之mycat读写分离安装配置

    最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考.本次系列终结大概包括以下内容:多数据库安装.mycat部署安装.数据库之读写分离 ...

  9. Mysql数据库搭建集群---实现主从复制,读写分离

    参考博客:https://blog.csdn.net/xlgen157387/article/details/51331244 A.  准备:多台服务器,且都可以互相随意访问root用户,都可以随意进 ...

随机推荐

  1. .net 中的 StringBuilder 和 TextWriter 区别

    最近闲来之余,看了一些开源的类库,看到有些类库喜欢用TextWriter类来记录相关的字符串数据,感到比较好奇,为啥不用StringBuilder类对象.于是在网上搜索了一番,总结了相关笔记. Str ...

  2. Java线程阻塞方法sleep()和wait()精炼详解

    版权声明:因为个人水平有限,文章中可能会出现错误,如果你觉得有描述不当.代码错误等内容或者有更好的实现方式,欢迎在评论区告诉我,即刻回复!最后,欢迎关注博主!谢谢 https://blog.csdn. ...

  3. vue v-for渲染数据出现DOMException: Failed to execute 'removeChild' on 'Node': The node .....

    在项目中,使用了vue的v-for渲染数组数据,在一次改变数组的时候出现异常报错,而实际的数组是已经变化过的了,页面卡死 网上找了一下原因,说是vue的DOM渲染的时候,删除之后DOM里面的还没有反应 ...

  4. Java io实现读取文件特殊内容进行替换

    最近公司在做一个项目其中一个需求是读取文件中的特殊字符在其后进行添加或删除字符操作,本来想直接使用randomAccessFile按行读取,读取到特殊字符就进行添加或删除操作,但是randomAcce ...

  5. 《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递

    4.4方法参数及传递 关于这个知识点,我想了很久该不该在这里阐述.因为这个知识点稍微有点晦涩,并且就算不了解也不影响用Java编写代码.不过笔者刚开始工作的时候,就是因为这块内容没有过多的关注,以至于 ...

  6. 吴恩达Machine Learning学习笔记(二)--多变量线性回归

    回归任务 多变量线性回归 公式 h为假设,theta为模型参数(代表了特征的权重),x为特征的值 参数更新 梯度下降算法 影响梯度下降算法的因素 (1)加速梯度下降:通过让每一个输入值大致在相同的范围 ...

  7. 内存操作【memset】【memcpy】

    void *memset(void *s, int c, unsigned long n); 将指针变量 s 所指向的前 n 字节的内存单元用一个"整数" c 替换,注意 c 是 ...

  8. C++赋值兼容原则理解

    –赋值兼容原则(派生类对象是基类对象,反之不成立)–基类指针强制转换成派生类指针–派生类中重定义基类成员(同名覆盖) 假设, 一个基类 "普通人", 一个派生类 "超人& ...

  9. 086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结

    086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结 本文知识点:面向对象基础(类和对象)总结 说明 ...

  10. ASP。NET MVC的部分视图和部分模型

    下载source - 1.7 MB 介绍 本文解决了返回视图内容包含表单元素的部分视图的问题. 代码重用是一种非常有用的节省时间的特性,任何优秀的工程师都会在他们的工作过程中构建许多有用的函数.对于W ...