k8s StatefulSet + Headless Service 部署reids集群
资源清单
configmap
apiVersion: v1 kind: ConfigMap metadata: name: redis-cluster-config namespace: redis-cluster data: redis-cluster.conf: | daemonize no supervised no protected-mode no bind 0.0.0.0 port 6379 cluster-announce-bus-port 16379 cluster-enabled yes appendonly yes cluster-node-timeout 5000 dir /data cluster-config-file /data/nodes.conf requirepass gNY7VRyxeIZqLLao masterauth gNY7VRyxeIZqLLao pidfile /data/redis.pid loglevel notice logfile /data/redis_log
statefulset
apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: redis-cluster name: redis-cluster namespace: redis-cluster spec: serviceName: redis-cluster-service-access replicas: 6 selector: matchLabels: app: redis-cluster template: metadata: labels: app: redis-cluster spec: # 定义了 Pod 在终止(比如被删除或重启)之前的优雅终止时间。在此期间,Kubernetes 会等待容器的进程有足够的时间进行清理工作,例如完成当前的请求或释放资源。 # 这里的配置:设置为 30 秒,表示在 Pod 被终止之前,容器有 30 秒的时间来优雅地关闭。这对 Redis 这样的服务至关重要,因为在关闭时需要确保数据被正确持久化和同步。 terminationGracePeriodSeconds: 30 containers: - name: redis image: redis:latest imagePullPolicy: IfNotPresent # 容器的退出信息会写入该文件。这对于容器的生命周期管理非常有用,Kubernetes 会读取该文件来获取容器退出的原因。 terminationMessagePath: /dev/termination-log # 容器退出信息的收集方式,File 表示 Kubernetes 会从 /dev/termination-log 文件中读取容器的退出状态信息。这通常用于调试容器问题 terminationMessagePolicy: File command: [ "redis-server", "/etc/redis/redis-cluster.conf" ] # 容器启动时的参数传递 args: # Redis 节点在集群中的对外 IP 地址 - "--cluster-announce-ip" # $(POD_IP) 是 Kubernetes 中的环境变量,表示当前 Pod 的 IP 地址。Redis 会将该 IP 地址作为集群通信时的公开 IP 地址。 - "$(POD_IP)" env: # 获取当前 Pod 所在节点的 IP 地址。status.hostIP 字段表示节点的 IP 地址,可以用于跨 Pod 的通信或者集群间的节点间连接。 - name: HOST_IP valueFrom: fieldRef: fieldPath: status.hostIP # 获取当前 Pod 的 IP 地址。这个环境变量对于 Redis 集群非常重要,通常会作为节点标识或集群发现时的参数传递给 Redis 服务。 - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP # 获取当前 Pod 的名称。这对于日志、调试或者在 Redis 集群内部识别节点非常有用。 - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: TZ value: "Asia/Shanghai" ports: - name: redis containerPort: 6379 protocol: TCP - name: cluster containerPort: 16379 protocol: TCP volumeMounts: - name: redis-conf mountPath: /etc/redis - name: pvc-data mountPath: /data volumes: - name: timezone hostPath: path: /usr/share/zoneinfo/Asia/Shanghai - name: redis-conf configMap: name: redis-cluster-config items: - key: redis-cluster.conf path: redis-cluster.conf volumeClaimTemplates: - metadata: name: pvc-data namespace: redis-cluster spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1G accessModes: - ReadWriteOnce storageClassName: "nfs-client"
service
apiVersion: v1 kind: Service metadata: name: redis-cluster-service-access namespace: redis-cluster spec: selector: app: redis-cluster #type: NodePort # 会话亲和性(Session Affinity)是一种机制,它能够将来自同一个客户端的请求始终转发至同一个后端的 Pod 对象。 # 当设置为 ClientIP 时,负载均衡器会根据客户端的 IP 地址来将来自同一个客户端的请求路由到同一个后端的 Pod 上。这有助于保持会话的一致性,特>别适用于需要维护会话状态的应用程序,如基于 HTTP 的 Web 应用程序。 #sessionAffinity: None # 当将 Service 的 clusterIP 字段设置为 None 时,Kubernetes 不会为该 Service 分配一个 Cluster IP 地址。 # clusterIP: None 的 Service 通常被称为 Headless Service。这种类型的 Service 主要用于需要直接访问后端 Pod 的场景。例如,当使用 StatefulSet 创建有状态的应用时,可能需要通过 DNS 名称直接访问每个 Pod,而不是通过 Service 的 Cluster IP 进行负载均衡。 clusterIP: None ports: - name: redis-6379 port: 6379 targetPort: 6379
查看资源
[root@master-1 redis]# kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE default ingressclass-ingress-nginx-controller-p22gm 1/1 Running 1 28h default ingressclass-ingress-nginx-controller-t5wz9 1/1 Running 1 28h default ingressclass-ingress-nginx-controller-tt7wg 1/1 Running 1 28h default nfs-client-provisioner-7d4f48bb8f-zbhfd 1/1 Running 1 28h kube-system calico-kube-controllers-7775799c8c-6x766 1/1 Running 2 28h kube-system calico-kube-controllers-7775799c8c-75bsz 1/1 Running 2 28h kube-system calico-kube-controllers-7775799c8c-gss8z 1/1 Running 2 28h kube-system calico-node-cczr6 1/1 Running 2 28h kube-system calico-node-k89f9 1/1 Running 2 28h kube-system calico-node-w4xgb 1/1 Running 2 28h kube-system calico-typha-5dc577d877-ht7rq 1/1 Running 2 28h kube-system coredns-5b476bb7fd-97ngb 1/1 Running 2 28h kube-system coredns-5b476bb7fd-kglll 1/1 Running 2 28h kube-system metrics-server-5bbd7cb4c6-hv8kj 1/1 Running 1 28h redis-cluster redis-cluster-0 1/1 Running 0 5m42s redis-cluster redis-cluster-1 1/1 Running 0 5m37s redis-cluster redis-cluster-2 1/1 Running 0 5m31s redis-cluster redis-cluster-3 1/1 Running 0 5m26s redis-cluster redis-cluster-4 1/1 Running 0 5m22s redis-cluster redis-cluster-5 1/1 Running 0 5m17s [root@master-1 redis]# kubectl get svc -n redis-cluster NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis-cluster-service NodePort 10.0.185.223 <none> 6379:40480/TCP,16379:31170/TCP 110s redis-cluster-service-access ClusterIP 10.0.123.124 <none> 6379/TCP 5m26s [root@master-1 redis]# kubectl get pvc -n redis-cluster NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-data-redis-cluster-0 Bound pvc-806c600e-81b7-48b6-b175-71433c843f87 1G RWO nfs-client 9m56s pvc-data-redis-cluster-1 Bound pvc-b88f244b-6b82-4734-8a88-5671dd0c5916 1G RWO nfs-client 9m51s pvc-data-redis-cluster-2 Bound pvc-4b98725d-03f7-4247-8731-2c6589b18ecd 1G RWO nfs-client 9m45s pvc-data-redis-cluster-3 Bound pvc-6a04fcc5-ed17-4c28-a3b6-99fce61fb60f 1G RWO nfs-client 9m40s pvc-data-redis-cluster-4 Bound pvc-46aae1a7-670a-4890-9f8f-5daf67638608 1G RWO nfs-client 9m36s pvc-data-redis-cluster-5 Bound pvc-1c286263-7377-442f-9792-209fa0ef898e 1G RWO nfs-client 9m31s [root@master-1 redis]# ll /opt/loki/ 总用量 48 drwxrwxrwx 2 root root 21 11月 25 09:42 default-test-claim-pvc-926415a9-1deb-422e-8c5a-0e02439836fc -rw-r--r-- 1 root root 385 11月 15 15:32 ingress.yaml drwxrwxrwx 3 root root 24 11月 25 10:00 monitor-prometheus-data-pvc-pvc-1d2d246f-378d-457e-b165-b1847849ae98 drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-0-pvc-806c600e-81b7-48b6-b175-71433c843f87 drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-1-pvc-b88f244b-6b82-4734-8a88-5671dd0c5916 drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-2-pvc-4b98725d-03f7-4247-8731-2c6589b18ecd drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-3-pvc-6a04fcc5-ed17-4c28-a3b6-99fce61fb60f drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-4-pvc-46aae1a7-670a-4890-9f8f-5daf67638608 drwxrwxrwx 3 root root 115 11月 26 14:20 redis-cluster-pvc-data-redis-cluster-5-pvc-1c286263-7377-442f-9792-209fa0ef898e
[root@master-1 redis]# kubectl get statefulset -n redis-cluster NAME READY AGE redis-cluster 6/6 8m7s
创建集群
[root@master-1 redis]# kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -a gNY7VRyxeIZqLLao --cluster create --cluster-replicas 1 $(kubectl get pods -n redis-cluster -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}') Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 10.244.247.13:6379 to 10.244.39.6:6379 Adding replica 10.244.84.140:6379 to 10.244.247.12:6379 Adding replica 10.244.39.7:6379 to 10.244.84.139:6379 M: 000359677ab1d4fc95664690868a87fb9d820627 10.244.39.6:6379 slots:[0-5460] (5461 slots) master M: b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d 10.244.247.12:6379 slots:[5461-10922] (5462 slots) master M: 65f80faf4c9340dc68329cbb06fc28c0f52de680 10.244.84.139:6379 slots:[10923-16383] (5461 slots) master S: a82e46f2663d75f50de4db6595b2938eb0bcd88a 10.244.39.7:6379 replicates 65f80faf4c9340dc68329cbb06fc28c0f52de680 S: 142b89643af3b7bc8e34aaab264f327534093d25 10.244.247.13:6379 replicates 000359677ab1d4fc95664690868a87fb9d820627 S: 603f7f1c95a9784b4de031247bfbd80fcd737317 10.244.84.140:6379 replicates b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d 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 10.244.39.6:6379) M: 000359677ab1d4fc95664690868a87fb9d820627 10.244.39.6:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 603f7f1c95a9784b4de031247bfbd80fcd737317 10.244.84.140:6379 slots: (0 slots) slave replicates b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d S: 142b89643af3b7bc8e34aaab264f327534093d25 10.244.247.13:6379 slots: (0 slots) slave replicates 000359677ab1d4fc95664690868a87fb9d820627 M: 65f80faf4c9340dc68329cbb06fc28c0f52de680 10.244.84.139:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d 10.244.247.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: a82e46f2663d75f50de4db6595b2938eb0bcd88a 10.244.39.7:6379 slots: (0 slots) slave replicates 65f80faf4c9340dc68329cbb06fc28c0f52de680 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
命令解释
kubectl get pods -n redis-cluster -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}' 10.244.39.6:6379 10.244.247.12:6379 10.244.84.139:6379 10.244.39.7:6379 10.244.247.13:6379 10.244.84.140:6379
kubectl get pods
:获取 Pod 列表。-n redis-cluster
:指定命名空间为redis-cluster
。-l app=redis-cluster
:使用标签选择器来过滤符合标签app=redis-cluster
的 Pods。-o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}'
:-o jsonpath
:输出格式为 JSONPath,以便提取和格式化数据。'{range.items[*]}{.status.podIP}:6379 {end}'
:这是 JSONPath 表达式,作用是遍历所有匹配的 Pod(即items[*]
),提取每个 Pod 的 IP 地址(.status.podIP
),然后附加:6379
,表示 Redis 的端口。
检查redis集群信息
[root@master-1 redis]# kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -a gNY7VRyxeIZqLLao Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> 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:141 cluster_stats_messages_pong_sent:135 cluster_stats_messages_sent:276 cluster_stats_messages_ping_received:130 cluster_stats_messages_pong_received:141 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:276 total_cluster_links_buffer_limit_exceeded:0 127.0.0.1:6379> cluster nodes 603f7f1c95a9784b4de031247bfbd80fcd737317 10.244.84.140:6379@16379 slave b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d 0 1732603545563 2 connected 142b89643af3b7bc8e34aaab264f327534093d25 10.244.247.13:6379@16379 slave 000359677ab1d4fc95664690868a87fb9d820627 0 1732603544755 1 connected 65f80faf4c9340dc68329cbb06fc28c0f52de680 10.244.84.139:6379@16379 master - 0 1732603545000 3 connected 10923-16383 b19ba40d442a20cb1d3bbe6eb47e30bc8a146a9d 10.244.247.12:6379@16379 master - 0 1732603545000 2 connected 5461-10922 a82e46f2663d75f50de4db6595b2938eb0bcd88a 10.244.39.7:6379@16379 slave 65f80faf4c9340dc68329cbb06fc28c0f52de680 0 1732603544000 3 connected 000359677ab1d4fc95664690868a87fb9d820627 10.244.39.6:6379@16379 myself,master - 0 0 1 connected 0-5460
写入100个key
[root@master-1 redis]# for line in {1..100};do kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a gNY7VRyxeIZqLLao -c set wacky_${line} ${line}; done Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK ...
获取key
[root@master-1 redis]# for line in {1..100};do kubectl exec -it redis-cluster-1 -n redis-cluster -- redis-cli -c -p 6379 -a gNY7VRyxeIZqLLao -c get wacky_${line}; done Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. "1" Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. "2" Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. "3" ...
获取当前节点所有的key
[root@master-1 redis]# kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a gNY7VRyxeIZqLLao Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> keys * 1) "wacky_82" 2) "wacky_73" 3) "wacky_86" ... 36) "wacky_98" 37) "wacky_43" 38) "wacky_47"
- Redis 集群将数据分布到多个节点(分片)上,每个节点存储一部分 key。一个 Redis 集群通常有多个节点,每个节点负责不同的 hash slots(哈希槽)。
keys *
只是返回当前节点上存储的 key,而不是整个集群中的 key。 - 如果你的 100 个 key 分布在多个节点(分片)上,
keys *
只会返回当前节点上的 key,而无法跨节点查找其他节点上的 key。因此,你看到的 38 个 key 可能只来自其中一个节点。
SCAN
命令适用于大数据量的情况,避免一次性返回大量数据造成阻塞。你可以在集群模式下对每个节点分别执行 SCAN
命令。
redis-cli -c -h <any-redis-node-ip> -p <any-redis-node-port> scan 0 match '*' count 100
遇到的问题:
1. pod DNS名称无法解析
StatefulSet
是一种 Kubernetes 控制器,旨在管理有状态的应用程序(如数据库、缓存等)。与 Deployment 不同,StatefulSet
提供了持久化的存储(通过 PersistentVolumeClaim),并且保证每个 Pod 都有一个唯一且稳定的网络标识符(DNS 名称)。这种稳定的标识符使得有状态应用能够识别和访问到自己特定的 Pod。
Headless Service 是 Kubernetes 中一种没有 ClusterIP 的服务(即 ClusterIP: None
)。当你为 StatefulSet 创建 Headless Service 时,Kubernetes 会为每个 Pod 创建一个唯一的 DNS 记录,而不是将流量负载均衡到服务后端的多个 Pod。
而实际上测试结果如下:
/ # nslookup redis-cluster-service-access Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local Name: redis-cluster-service-access Address 1: 10.244.247.19 10-244-247-19.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 2: 10.244.84.146 10-244-84-146.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 3: 10.244.39.16 10-244-39-16.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 4: 10.244.84.147 10-244-84-147.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 5: 10.244.247.18 10-244-247-18.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 6: 10.244.39.17 10-244-39-17.redis-cluster-service-access.redis-cluster.svc.cluster.local / # nslookup redis-cluster-0.redis-cluster-service-access Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local nslookup: can't resolve 'redis-cluster-0.redis-cluster-service-access'
可以看到 svc解析出来结果是10-244-247-19.redis-cluster-service-access.redis-cluster.svc.cluster.local,而不是redis-cluster-0.redis-cluster-service-access.redis-cluster.svc.cluster.local
而是直接解析pod的 dns名称也不能解析。
问题原因-
Headless Service 配置
Headless Service(ClusterIP: None
)不会创建单一的集群虚拟 IP,而是直接暴露每个 Pod 的 DNS 记录。通常,配合 StatefulSet 使用时,每个 Pod 都会有一个固定的 DNS 名称,如redis-cluster-0.redis-cluster-service-access.redis-cluster.svc.cluster.local
。 -
无特定 DNS 条目
你的nslookup redis-cluster-service-access
返回了一组 IP 地址(10-244-XX-XX
格式),说明redis-cluster-service-access
是一个 Headless Service,直接返回 Pod 的 IP 地址,而不是命名格式的 DNS。 -
Pod 名称解析失败
nslookup redis-cluster-0.redis-cluster-service-access.redis-cluster
无法解析,可能是因为:- StatefulSet 的
serviceName
字段未正确配置。 - Pod 启动时未正确注册对应的 DNS 记录。
- Headless Service 或 StatefulSet 的命名不匹配。
- StatefulSet 的
-
检查 StatefulSet 配置 确保 StatefulSet 的
serviceName
指向你的 Headless Service:
serviceName: redis-cluster-service-access
检查 Headless Service 配置 确保 Headless Service 配置正确:
apiVersion: v1 kind: Service metadata: name: redis-cluster-service-access spec: clusterIP: None selector: app: redis-cluster
serviceName
的含义
serviceName
是指向一个 Headless Service(ClusterIP: None
)的名称。- 它用于定义 StatefulSet 中 Pod 的 DNS 子域(
subdomain
),从而支持 StatefulSet 的 Pod 创建具有稳定网络标识(DNS 名称)。
每个 Pod 会基于 serviceName
和其 hostname
生成一个固定的 FQDN(完全限定域名),格式如下:
<pod-name>.<serviceName>.<namespace>.svc.cluster.local
例如:
- Pod 名称:
redis-cluster-0
serviceName
:redis-cluster-service-access
- 命名空间:
redis-cluster
- DNS 名称:
redis-cluster-0.redis-cluster-service-access.redis-cluster.svc.cluster.local
-
配合 Headless Service 的 Pod 直连
- 指定
serviceName
后,Headless Service 会为每个 Pod 创建独立的 DNS 记录(而非单一的虚拟 IP)。这允许客户端直接通过 Pod 的 DNS 名称访问,而无需负载均衡。
- 指定
-
状态管理支持
serviceName
是 StatefulSet 中Pod
的唯一标识关联点,用于实现 Pod 的有序部署、更新和删除。没有正确的serviceName
,StatefulSet 将无法为 Pod 分配正确的子域。
与 Headless Service 的关系
- StatefulSet 和 Headless Service 必须配合使用。
- Headless Service 的
selector
必须和 StatefulSet 的 Pod 标签匹配,否则无法正确关联 Pod。例如:
apiVersion: v1 kind: Service metadata: name: redis-cluster-service-access namespace: redis-cluster spec: clusterIP: None selector: app: redis-cluster
如果不指定 serviceName
会怎样?
- 如果
serviceName
未指定:- StatefulSet 无法生成 Pod 的 DNS 子域。
- Pod 的 FQDN 不可用,导致基于 DNS 的通信可能失败。
- StatefulSet 仍会正常运行,但 DNS 功能将受限。
修改statefulset清单文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: redis-cluster name: redis-cluster namespace : redis-cluster spec: serviceName: redis-cluster-service-access replicas: 6 selector: matchLabels: app: redis-cluster template: metadata: labels: app: redis-cluster |
再次测试
/ # nslookup redis-cluster-service-access Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local Name: redis-cluster-service-access Address 1: 10.244.247.21 redis-cluster-4.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 2: 10.244.84.149 redis-cluster-3.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 3: 10.244.247.20 redis-cluster-1.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 4: 10.244.39.19 redis-cluster-5.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 5: 10.244.84.148 redis-cluster-0.redis-cluster-service-access.redis-cluster.svc.cluster.local Address 6: 10.244.39.18 redis-cluster-2.redis-cluster-service-access.redis-cluster.svc.cluster.local
/ # nslookup redis-cluster-0.redis-cluster-service-access.redis-cluster Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local Name: redis-cluster-0.redis-cluster-service-access.redis-cluster Address 1: 10.244.84.148 redis-cluster-0.redis-cluster-service-access.redis-cluster.svc.cluster.local
2. redis集群主备切换
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现