• zookeeper分布式读写锁


    获取写锁:

    1、创建临时序号单调递增节点

    2、若存在比本节点序号小的读或者写节点,则设置观察点,观察仅小于本节点序号的节点。收到观察点删除事件,则获得写锁

    3、获得写锁后,开始执行业务。业务完成后,删除本节点

    获取写锁:

    1、创建临时序号单调递增节点

    2、若存在比本节点序号小的写节点,则设置观察点,观察仅小于本节点序号的写节点。收到观察点删除事件,则获得读锁

    3、获得读锁后,开始执行业务。业务完成后,删除本节点

    func ZookeeperInit() error {
    
        var hosts = []string{"192.168.228.141:2181"}
        conn, _, err := zk.Connect(hosts, time.Second*5)
        if err != nil {
            logrus.Errorf(err.Error())
            return err
        }
        defer conn.Close()
    
        // 创建Lock节点(永久节点)
        var lockPath = "/Lock"
        var lockData []byte = []byte("Lock")
        var lockFlags int32 = 0
        var acls = zk.WorldACL(zk.PermAll)
        _, err = conn.Create(lockPath, lockData, lockFlags, acls)
        if err != nil {
            if 0 == strings.Compare("zk: node already exists", err.Error()) {
                logrus.Infof("Create Node %s Success", lockPath)
                return nil
            }
            logrus.Errorf("%s", err.Error())
            return err
        }
    
        return nil
    }
    func Lock() (lockName string, err error) {
    
        // 创建临时写节点
        var hosts = []string{"192.168.228.141:2181"}
        conn, _, err := zk.Connect(hosts, time.Second*5)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
        defer conn.Close()
    
        // 获取当前子节点
        children, _, err := conn.Children("/Lock")
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
    
        fmt.Println("children", children)
        maxChild := GetMaxchild(children)
    
        // 创建当前节点
        var wLockPath = "/Lock/w"
        var wLockData []byte = []byte(strconv.FormatInt(time.Now().Unix(), 10))
        var wLockFlags int32 = 2 // 永久序列增长节点
        var acl = zk.WorldACL(zk.PermAll)
    
        lockPath, err := conn.Create(wLockPath, wLockData, wLockFlags, acl)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
    
        if "" != maxChild {
            // 对最大子节点设置观察点
            _, _, ech, err := conn.ExistsW(maxChild)
            if err != nil {
                logrus.Errorf("%s", err.Error())
                return "", err
            }
            timeout := 60 // 超时时间10s
            for timeout > 0 {
                select {
                case _, ok := <-ech:
                    if ok {
                        return lockPath, nil
                    }
                default:
                    time.Sleep(time.Second)
                    timeout--
                }
            }
            return "", nil
        } else {
            return lockPath, nil
        }
    
        return "", nil
    }
    
    func Unlock(lockName string) error {
    
        var hosts = []string{"192.168.228.141:2181"}
        conn, _, err := zk.Connect(hosts, time.Second*5)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return err
        }
        defer conn.Close()
    
        // 删除节点
        err = conn.Delete(lockName, 0)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return err
        }
    
        return nil
    }
    
    func RLock() (lockName string, err error) {
        // 创建临时写节点
        var hosts = []string{"192.168.228.141:2181"}
        conn, _, err := zk.Connect(hosts, time.Second*5)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
        defer conn.Close()
    
        // 获取当前子节点
        children, _, err := conn.Children("/Lock")
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
    
        maxChild := GetMaxWritechild(children)
    
        // 创建子节点
        var wLockPath = "/Lock/r"
        var wLockData []byte = []byte(strconv.FormatInt(time.Now().Unix(), 10))
        var wLockFlags int32 = 2 // 永久序列增长节点
        var acl = zk.WorldACL(zk.PermAll)
    
        lockPath, err := conn.Create(wLockPath, wLockData, wLockFlags, acl)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return "", err
        }
    
        if "" != maxChild {
            // 对最大子节点设置观察点
            _, _, ech, err := conn.ExistsW(maxChild)
            if err != nil {
                logrus.Errorf("%s", err.Error())
                return "", err
            }
            timeout := 60 // 超时时间10s
            for timeout > 0 {
                select {
                case _, ok := <-ech:
                    if ok {
                        return lockPath, nil
                    }
                default:
                    time.Sleep(time.Second)
                    timeout--
                }
            }
            return "", nil
        } else {
            return lockPath, nil
        }
    
        return "", nil
    }
    
    func RUnlock(lockName string) error {
        var hosts = []string{"192.168.228.141:2181"}
        conn, _, err := zk.Connect(hosts, time.Second*5)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return err
        }
        defer conn.Close()
    
        // 删除节点
        err = conn.Delete(lockName, 0)
        if err != nil {
            logrus.Errorf("%s", err.Error())
            return err
        }
    
        return nil
    }
    
    func GetMaxchild(children []string) (child string) {
        if 0 == len(children) {
            return ""
        }
    
        var maxChild = children[0]
        maxIndex := maxChild[1:]
        for _, value := range children {
            curIndex := value[1:]
            if curIndex > maxIndex {
                maxIndex = curIndex
            }
            maxChild = value
        }
    
        return maxChild
    }
    
    func GetMaxWritechild(children []string) (child string) {
        //过滤所有写节点
        writeChildren := make([]string, 0)
        for _, value := range children {
            if strings.HasPrefix(value, "w") {
                writeChildren = append(writeChildren, value)
            }
        }
    
        if 0 == len(writeChildren) {
            return ""
        }
    
        var maxChild = children[0]
        maxIndex := maxChild[1:]
        for _, value := range children {
            curIndex := value[1:]
            if curIndex > maxIndex {
                maxIndex = curIndex
            }
            maxChild = value
        }
    
        return maxChild
    }
  • 相关阅读:
    记录一次无法很好解决的问题
    java与进制转换
    花了点时间写了下测试框架
    利用eclipse或者pycharm编写monkeyrunner脚本,cmd打开应用“转转”并截图保存到D盘
    Instrumentation
    关于学生机受控应用的问题总结
    忙里偷闲一天
    linux下python3的安装(已安装python2的情况下)
    ROS上利用usb_cam读取摄像头图像
    ch8 -- directMethod
  • 原文地址:https://www.cnblogs.com/zengyjun/p/10139098.html
Copyright © 2020-2023  润新知