ZooKeeper基础

news2024/11/18 12:22:12

一、概念

架构:

  • Client/Server
  • Ensemble(集群,ZK服务器组),最小节点数为3
  • ZK Leadera
  • ZK Follower

ZooKeeper数据模型

  • znode:用于存储数据,分为持久的(default)、临时的、顺序的
  • stat(metadata)

Session:

  • Client连接到Server的时候分配一个SessionID
  • Client发送心跳保持Session
  • Session结束时基于该Session创建的znode也会删除

Watches:

  • 用于Client 监视 znode,主要用于接收ZooKeeper集合中的znone更改通知

二、部署

2.1.单节点部署

Docker镜像:https://github.com/31z4/zookeeper-docker/tree/master/3.8.0

启动命令:

# 主要是config、data和datalog三个要持久化
docker run -d --name=zookeeper -v /opt/zookeeper/data/:/data/ -v /opt/zookeeper/datalog/:/datalog/ -v /opt/zookeeper/conf/:/conf/ -p 2181:2181 zookeeper:3.8.0

默认的配置(docker-entrypoint.sh写入)

# cat /opt/zookeeper/conf/zoo.cfg

# 存放内存数据结构的snapshot
dataDir=/data

# wal日志存放目录
dataLogDir=/datalog


# zk 使用的基本时间单位,以毫秒为单位。用于做心跳时间的间隔,最小会话超时将是 tickTime 的两倍。
tickTime=2000 

# 集群初始化的时候,follower连接leader允许的心跳数(tickTime)
initLimit=5

# flower和leader之间的心跳过期时间
syncLimit=2

# 自动删除 客户端与服务端交互的时候产生的日志snapRetainCount以快照为限制,purgeInterval以时间为限制
# 自动删除的话,可能会影响性能?
autopurge.snapRetainCount=3
autopurge.purgeInterval=0

# 一个客户端的连接数限制
maxClientCnxns=60

standaloneEnabled=true
admin.enableServer=true

# 2888: peer之间通信的端口
# 3888: 选举新的leader使用的端口
# 2818:客户端连接的端口
server.1=localhost:2888:3888;2181

启动后,会在data目录下生成myid文件(zk节点的id)和数据文件(version-2/snapshot.0)
使用Cli连接ZK

docker exec -it zookeeper /apache-zookeeper-3.8.0-bin/bin/zkCli.sh -server 127.0.0.1:2181
Connecting to localhost:2181
...

# 一些基本操作

ls /
create /zk_test my_data  # 创建znode, -s顺序znode, -e临时znode

get /zk_test 

set /zk_test junk

stat /zk_test  # 查看节点状态 

delete /zk_test

使用go sdk实现简单的CUR + Watch
package main

import (
    "fmt"
    "github.com/go-zookeeper/zk"
    "time"
)


// https://pkg.go.dev/github.com/go-zookeeper/zk#Conn.Create
func create(c *zk.Conn, path string, data []byte){
    // flags
    // 0:永久
    // zk.FlagEphemeral
    // zk.FlagSequence
    // 3:Ephemeral和Sequence
    var flags int32 = 0
    
    path, err := c.Create(path, data, flags, zk.WorldACL(zk.PermAll))
    if err != nil {
        fmt.Println("创建失败", err)
        return
    }
    fmt.Println("创建成功", path)
}

func get(c *zk.Conn, path string){
    
    data, state, err := c.Get(path)
    if err != nil {
        fmt.Println("获取失败")
        return
    }
    fmt.Println("data", string(data))
    fmt.Println("state", state)
    
}

func update(c *zk.Conn, path string, data []byte){
    _, sate, _ := c.Get(path)
    _, err := c.Set(path, data, sate.Version)
    if err != nil {
        fmt.Println("更新失败", err)
        return
    }
    fmt.Println("更新成功")
}


func main() {
    conn, _, err := zk.Connect([]string{"192.168.56.4"}, time.Second)
    if err != nil {
        panic(err)
    }
    defer conn.Close()
    
    path := "/test-path"
    data := []byte("test-data")
    
    create(conn, path, data)
    get(conn, path)
    
    newData := []byte("new-data")
    update(conn, path, newData)
    get(conn, path)
    
    exists, state, eventChannel, err := conn.ExistsW("/test-path")
    if err != nil {
        panic(err)
    }
    // 如果监听的path有修改,就会收到通知(只会触发一次)
    // 有空的时候实现一下循环监听
    go func() {
        e := <-eventChannel
        fmt.Println("========================")
        fmt.Println("path:", e.Path)
        fmt.Println("type:", e.Type.String())
        fmt.Println("state:", e.State.String())
        fmt.Println("========================")
    }()
    fmt.Println("exists", exists)
    fmt.Println("state", state)
    time.Sleep(100 * time.Second)
}

2.2.Kubernetes部署ZK集群

部署zk集群可以使用statefulset,也可以使用zk operator
statefulset实现比较简单,能满足需求的情况下,可以不用引入zk operator

当前用statefulset实现,使用的镜像启动脚本:https://github.com/kow3ns/kubernetes-zookeeper/blob/master/docker/scripts/start-zookeeper

这个启动脚本最重要的通过hostname获取每个zk节点的myid,让statefulset可以支持zk集群。 然后就是把传入的参数转化成配置文件。镜像用的是ubuntu14,可以替换成我们用的统一基础镜像,后续的升级版本或者新增的配置可以修改Dockerfile和启动脚本

zookeeper@zk-0:/var/lib$ cat /opt/zookeeper/conf/zoo.cfg 
#This file was autogenerated DO NOT EDIT
clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/data/log
tickTime=2000
initLimit=10
syncLimit=5
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
autopurge.snapRetainCount=3
autopurge.purgeInteval=12
server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888

k8s部署ZK集群实现高可用主要的点:

  1. 3副本Statefulset(3节点以上,奇数副本数)
  2. 挂载Volume,主要是给data和datalog使用
  3. 通过PodAntiAffinity让不同的Pod运行在不同的node之上,最好是不同AZ上的节点
  4. 配置PDB,至少要保证半数以上的节点存活,比如3节点就要保证2个节点存活
  5. 创建一个Headless-Service,用于zk peer之间互访
  6. 创建一个ClusterIP类型的Service,用于client访问zk集群
  7. 对于各个配置项的优化,目前暂不研究
# 用于zk集群peer之间通信的Headless Service,让zk peer通过dns的方式发现对方
apiVersion: v1
kind: Service
metadata:
  name: zk-hs
  labels:
    app: zk
spec:
  ports:
  - port: 2888
    name: server
  - port: 3888
    name: leader-election
  clusterIP: None
  selector:
    app: zk
---

# 用于客户端访问zk集群的ClusterIP Service
apiVersion: v1
kind: Service
metadata:
  name: zk-cs
  labels:
    app: zk
spec:
  ports:
  - port: 2181
    name: client
  selector:
    app: zk

---
# PDB,主动驱逐场景下保证最多只有1个zk节点不可用
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  selector:
    matchLabels:
      app: zk
  maxUnavailable: 1

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zk
spec:
  selector:
    matchLabels:
      app: zk
  serviceName: zk-hs
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: zk
    spec:
      # affinity:
      #   podAntiAffinity:
      #     requiredDuringSchedulingIgnoredDuringExecution:
      #       - labelSelector:
      #           matchExpressions:
      #             - key: "app"
      #               operator: In
      #               values:
      #               - zk
      #         topologyKey: "kubernetes.io/hostname"
      containers:
      - name: zk
        imagePullPolicy: IfNotPresent
        image: "guglecontainers/kubernetes-zookeeper:1.0-3.4.10"
        resources:
          limits:
            memory: "512M"
            cpu: 0.5
        #   requests:
        #     memory: "1Gi"
        #     cpu: "0.5"
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        command:
        - sh
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/zookeeper
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
      volumes:
      - name: "datadir"
        emptyDir: {}

  # 挂载Volume
  # volumeClaimTemplates:
  # - metadata:
  #     name: datadir
  #   spec:
  #     accessModes: [ "ReadWriteOnce" ]
  #     resources:
  #       requests:
  #         storage: 10Gi

Refs

  • https://zookeeper.apache.org/doc/r3.8.0/index.html
  • http://www.dba.cn/book/zookeeper/ZOOKEEPERZhongWenShouCe/ZOOKEEPERGaiShu.html
  • https://hub.docker.com/_/zookeeper
  • https://kubernetes.io/zh/docs/tutorials/stateful-application/zookeeper/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一次服务器非法重启后导致的故障排查记录

作者&#xff1a;JackTian 来源&#xff1a;公众号「杰哥的IT之旅」 ID&#xff1a;Jake_Internet 转载请联系授权&#xff08;微信ID&#xff1a;Hc220088&#xff09; 原文地址&#xff1a;一次服务器非法重启后导致的故障排查记录 大家好&#xff0c;我是杰哥。 前段时间遇…

贪婪算法(Huffman编码)

如果一个算法分阶段的工作&#xff0c;并且在每一个阶段都认为所做的决定是最好的&#xff0c;而不考虑将来的后果&#xff0c;这样的算法就叫做贪婪算法。贪婪算法只考虑当前局部的最优解&#xff0c;而不去考虑全局的情况&#xff0c;如果最终得到的结果是全局最优的&#xf…

麻雀优化CNN超参数用于回归MATLAB

在CNN模型的构建中&#xff0c;涉及到特别多的超参数&#xff0c;比如&#xff1a;学习率、训练次数、batchsize、各个卷积层的卷积核大小与卷积核数量&#xff08;feature map数&#xff09;&#xff0c;全连接层的节点数等。直接选择的话&#xff0c;很难选到一组满意的参数&…

如何理解关系型数据库的常见设计范式?

目录理清基础概念实体属性元组分组函数依赖完全函数依赖部分函数依赖传递函数依赖码全码理解六范式第一范式&#xff08;1NF&#xff09;第二范式&#xff08;2NF&#xff09;第三范式&#xff08;3NF&#xff09;巴斯-科德范式&#xff08;BCNF&#xff0c;Boyce-Codd Normal …

基于STM32的智能家居系统设计

目录 第1章 前言 1 1.1 课题研究的背景和实际意义 1 1.1.1课题背景 1 1.1.2实际意义 1 1.2国内外发展现状、存在问题以及前景 2 1.2.1发展现状 2 1.2.2存在问题 2 1.2.3发展前景 2 1.3 主要工作、内容安排及预期成果 3 1.3.1主要研究工作 3 1.3.2预期成果 3 第2章 总体设计方案…

安卓4.X版本ssl: sslv3 alert handshake failure 握手失败

低版本https握手失败错误查看接口的协议改写代码&#xff08;网络访问采用原生的HttpsURLConnection&#xff09;参考博文&#xff1a;https://www.cnblogs.com/lwbqqyumidi/p/12063489.htmlhttps://blog.csdn.net/qq_16117167/article/details/52621112错误 如图所示&#xf…

linux进程概念

目录 1、进程的基本概念 2、进程控制块 - PCB task_struct内容分类 3、查看进程 通过ps命令查看进程 通过proc查看进程 4、通过系统调用获取进程标示符 5、通过系统调用创建进程-fork初识 6、进程状态 操作系统进程状态 linux进程状态 僵尸进程 孤儿进程 僵尸进…

计算机网络-谢希仁-第7版 第1章 概述

计算机网络-谢希仁-第7版 第1章 概述1.011.021.031.071.081.091.101.111.121.131.141.161.171.181.191.201.211.221.241.251.26计算机网络谢希仁版&#xff08;第七版&#xff09;答案 1.01 计算机网络可以向用户提供哪些服务&#xff1f; 计算机网络使用户在计算机之间传送数…

【Linux】Linux下的编译器——gcc/g++

&#x1f4ac;推荐一款模拟面试、刷题神器 、从基础到大厂面试题&#xff1a;&#x1f449;点击跳转刷题网站进行注册学习 目录 一、编译的过程 1、预处理阶段 1.1预处理的工作——头文件展开、去注释、宏替换、条件编译 1.2外部定义宏&#xff08;-D选项&#xff09; 1.…

会话跟踪技术(Cookie、Session)

目录一、CookieCookie的基本使用发送Cookie获取CookieCookie原理Cookie使用细节二、SessionSession基本使用Session原理Session使用细节三、小结四、登录注册案例会话&#xff1a;用户打开浏览器&#xff0c;访问Web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开…

数据结构之堆的应用

系列文章目录 数据结构之堆_crazy_xieyi的博客-CSDN博客 文章目录 前言一、Top-k问题 1.前K个最小数&#xff08;第k个最小数&#xff09; 2.前K个最大数&#xff08;第K个最大数&#xff09;二、堆排序 1.从小到大排序&#xff08;建大根堆&#xff09;2.从大到…

【2022研电赛】安谋科技企业命题一等奖:基于EAIDK-610的中国象棋机器人对弈系统

本文为2022年第十七届中国研究生电子设计竞赛安谋科技企业命题一等奖作品分享&#xff0c;参加极术社区的【有奖活动】分享2022研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&#xff01; 基于EAIDK-610的中国象棋机器人对弈系统 参赛单位&#xff1a;西安邮电大学…

硬件开发趋势与技术探索

LiveVideoStackCon 2022 音视频技术大会 北京站将于11月25日至26日在北京丽亭华苑酒店召开&#xff0c;本次大会将延续【音视频无限可能】的主题&#xff0c;邀请业内众多企业及专家学者&#xff0c;将他们在过去一年乃至更长时间里对音视频在更多领域和场景下应用的探索、在实…

2023届C/C++软件开发工程师校招面试常问知识点复盘Part 8

目录52、vector<string>是怎么存储的&#xff1f;53、epoll的底层原理53.1 对比select和poll53.2 ET和LT的工作模式54、进程、线程、协程的理解和他们的通信方式54.1 进程的含义54.2 线程的含义54.3 协程的含义54.4 进程间通信IPC54.5 线程间通信方式55、define宏定义的用…

【JavaDS】优先级队列(PriorityQueue),堆,Top-k问题

✨博客主页: 心荣~ ✨系列专栏:【Java实现数据结构】 ✨一句短话: 难在坚持,贵在坚持,成在坚持! 文章目录一. 堆1. 堆的概念2. 堆的存储方式3. 堆的创建4. 元素入堆5. 元素出堆6. 获取堆中元素二. 优先级堆列(PriorityQueue)1. 优先级队列2. PriorityQueue的特性3. 集合框架中P…

万字启程——零基础~前端工程师_养成之路001篇

目录 什么是前端 什么是后端 前端和后端的区别 前端工程师职责 后端工程师职责 前端的核心技术 HTML CSS JavaScript RESTful结构 特点 HTTP请求方式有哪些 目前最火的前端框架Vue vue优点 vue的响应式编程、组件化 搭建编程环境 什么是编程环境 前端的编程环…

华为云CDN,海量资源智能路由,让内容传输更快一步

华为云CDN,海量资源智能路由,让内容传输更快一步 云服务对于我们生活的影响已经愈发深入&#xff0c;在数字化转型的大背景下&#xff0c;城市管理、公共交通、医疗健康等领域都需要云服务的支持。华为云作为国内知名的云服务平台&#xff0c;以技术强、更可靠、资源多以及帮肋…

基于CentOS 7.9操作系统应用httpd配置本地镜像(本地yum源)

记录&#xff1a;301 场景&#xff1a;配置离线本地镜像源(本地yum源)的三种方式&#xff1a;直接使用iso镜像包配置、使用httpd服务应用iso镜像包配置、使用httpd服务应用rpm包配置。在内网环境或者局域网环境&#xff0c;基于CentOS 7.9操作系统应用httpd配置本地镜像(本地y…

手把手带你玩转Spark机器学习-深度学习在Spark上的应用

系列文章目录 手把手带你玩转Spark机器学习-专栏介绍手把手带你玩转Spark机器学习-问题汇总手把手带你玩转Spark机器学习-Spark的安装及使用手把手带你玩转Spark机器学习-使用Spark进行数据处理和数据转换手把手带你玩转Spark机器学习-使用Spark构建分类模型手把手带你玩转Spa…

Python学习笔记(十三)——编译错误和异常处理

异常和异常类 Python常见错误 语法错误 源代码存在拼写语法错 误&#xff0c;这些错误导致Python 编译器无法把Python源代 码转换为字节码&#xff0c;故也称 之为编译错误。>>> print("我爱山大"} SyntaxError: invalid syntax 运行时错误 • 程序中没有…