从源码了解zookeeper的会话机制,2024年最新大数据开发程序员必经的实践之路

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

long waitTime = sessionExpiryQueue.getWaitTime();
if (waitTime > 0) {
    Thread.sleep(waitTime);
    continue;
}

会话的过期

SessionTracker先计算离下一次结算会话还有多久时间,如果还没到时间就sleep需要等待的秒数

for (SessionImpl s : sessionExpiryQueue.poll()) {
                    //统计过期的个数
                    ServerMetrics.getMetrics().STALE_SESSIONS_EXPIRED.add(1);
                    //设置会话关闭状态
                    setSessionClosing(s.sessionId);
                    //关闭会话
                    expirer.expire(s);
                }

然后取出sessionExpiryQueue中的元素,统计个数,设置状态并关闭

    private final ConcurrentHashMap<E, Long> elemMap = new ConcurrentHashMap<>();
    /**
     * The maximum number of buckets is equal to max timeout/expirationInterval,
     * so the expirationInterval should not be too small compared to the
     * max timeout that this expiry queue needs to maintain.
     */
    private final ConcurrentHashMap<Long, Set<E>> expiryMap = new ConcurrentHashMap<>();

    private final AtomicLong nextExpirationTime = new AtomicLong();
    private final int expirationInterval;

ExpiryQueue是zookeeper中的数据结构,维护了一个元素map用来存放会话,key是sessionId,value是还剩多久过期。expiryMap是会话桶集合,key是桶号,value是桶内元素,nextExpirationTime用来和expirationInterval一起计算下次的过期时刻。

会话的续期

会话的管理实际上就是对ExpiryQueue的操作。

client即使没有操作也会向server发送心跳防止会话过期,server一旦接受到了session的信息就会调用ExpiryQueue的update方法来更新

    public Long update(E elem, int timeout) {
        //取出之前在哪一个桶
        Long prevExpiryTime = elemMap.get(elem);
        long now = Time.currentElapsedTime();
        //计算现在是在哪一个桶
        Long newExpiryTime = roundToNextInterval(now + timeout);
        //如果是同一个桶 do nothing
        if (newExpiryTime.equals(prevExpiryTime)) {
            // No change, so nothing to update
            return null;
        }


        Set<E> set = expiryMap.get(newExpiryTime);
        //如果改桶还没有初始化,就新建一个set,放入expiryMap,注意线程安全
        if (set == null) {
            // Construct a ConcurrentHashSet using a ConcurrentHashMap
            set = Collections.newSetFromMap(new ConcurrentHashMap<>());
            // Put the new set in the map, but only if another thread
            // hasn't beaten us to it
            //防止多次放入污染数据
            Set<E> existingSet = expiryMap.putIfAbsent(newExpiryTime, set);
            if (existingSet != null) {
                set = existingSet;
            }
        }
//        放入桶
        set.add(elem);

        // Map the elem to the new expiry time. If a different previous
        // mapping was present, clean up the previous expiry bucket.
        prevExpiryTime = elemMap.put(elem, newExpiryTime);
//        从旧桶中移除
        if (prevExpiryTime != null && !newExpiryTime.equals(prevExpiryTime)) {
            Set<E> prevSet = expiryMap.get(prevExpiryTime);
            if (prevSet != null) {
                prevSet.remove(elem);
            }
        }
        return newExpiryTime;
    }

每当有新的会话加入就会调用trackSession来加入ExpiryQueue中

会话的新建

    public synchronized boolean trackSession(long id, int sessionTimeout) {
        boolean added = false;
//        是否已经track了
        SessionImpl session = sessionsById.get(id);
        if (session == null) {
            session = new SessionImpl(id, sessionTimeout);
        }

//        防止重复放入
        SessionImpl existedSession = sessionsById.putIfAbsent(id, session);

        if (existedSession != null) {
            session = existedSession;
        } else {
            added = true;
            LOG.debug("Adding session 0x{}", Long.toHexString(id));
        }

        if (LOG.isTraceEnabled()) {
            String actionStr = added ? "Adding" : "Existing";
            ZooTrace.logTraceMessage(
                LOG,
                ZooTrace.SESSION_TRACE_MASK,
                "SessionTrackerImpl --- " + actionStr
                + " session 0x" + Long.toHexString(id) + " " + sessionTimeout);
        }

        updateSessionExpiry(session, sessionTimeout);
        return added;
    }

这样会话管理的新建,过期,续期都看到了

分桶算法的源码

    private long roundToNextInterval(long time) {
        return (time / expirationInterval + 1) * expirationInterval;
    }


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
![img](https://img-blog.csdnimg.cn/img_convert/2b04f66c73c39e1b01a7ac93164d9e7a.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-Xe2FKQLK-1713172636134)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大数据开发工程师需要具备高可用性的知识是非常重要的。以下是一些与高可用相关的知识点: 1. 数据冗余与备份:了解数据冗余的概念,通过数据备份和复制来保证数据的可靠性和高可用性。熟悉常用的数据备份策略和技术,如RAID、分布式文件系统等。 2. 容错与故障转移:了解容错和故障转移的机制和技术,如故障转移集群、冗余节点、负载均衡等。熟悉常见的容错与故障转移方案,如Hadoop的NameNode故障转移、Zookeeper分布式协调服务等。 3. 高可用架构设计:熟悉设计高可用架构的原则和方法,如去中心化、分布式架构、多活架构等。了解常见的高可用架构模式,如主从复制、主备模式、集群模式等。 4. 监控与告警:了解监控和告警系统的原理和实现方式,如使用监控指标来判断系统状态、配置告警规则来及时发现异常等。熟悉常见的监控工具和框架,如Nagios、Zabbix、Prometheus等。 5. 自动化运维:掌握自动化运维的技术和工具,如自动化部署、自动化测试、自动化运维工具等。了解常用的自动化运维框架,如Ansible、SaltStack、Docker等。 6. 容量规划与扩展:了解容量规划和扩展的方法和技术,通过监控和性能评估来预测系统的负载和资源需求。熟悉常见的扩展方式,如水平扩展、垂直扩展、分布式扩展等。 7. 故障排除与性能优化:具备故障排除和性能优化的能力,能够快速定位和解决系统故障和性能问题。熟悉常见的故障排除和性能优化工具和方法,如日志分析工具、性能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值