感受:
其实我投简历的时候,都不太敢投递阿里。因为在阿里一面前已经过了字节的三次面试,投阿里的简历一直没被捞,所以以为简历就挂了。
特别感谢一面的面试官捞了我,给了我机会,同时也认可我的努力和态度。对比我的面经和其他大佬的面经,自己真的是运气好。别人8成实力,我可能8成运气。所以对我而言,我要继续加倍努力,弥补自己技术上的不足,以及与科班大佬们基础上的差距。希望自己能继续保持学习的热情,继续努力走下去。
也祝愿各位同学,都能找到自己心动的offer。
分享我在这次面试前所做的准备(刷题复习资料以及一些大佬们的学习笔记和学习路线),都已经整理成了电子文档
if (result.getStatus().equals(Status.EXCEPTION)) {
throw new LeafServerException(result.toString());
}
return String.valueOf(result.getId());
}
}
访问:http://127.0.0.1:8080/api/segment/get/leaf-segment-test
,结果正常返回,感觉没毛病,但当查了一下数据库表中数据时发现了一个问题。
通常在用号段模式的时候,取号段的时机是在前一个号段消耗完的时候进行的,可刚刚才取了一个ID,数据库中却已经更新了max_id
,也就是说leaf
已经多获取了一个号段,这是什么鬼操作?
Leaf
为啥要这么设计呢?
Leaf
希望能在DB中取号段的过程中做到无阻塞!
当号段耗尽时再去DB中取下一个号段,如果此时网络发生抖动,或者DB发生慢查询,业务系统拿不到号段,就会导致整个系统的响应时间变慢,对流量巨大的业务,这是不可容忍的。
所以Leaf
在当前号段消费到某个点时,就异步的把下一个号段加载到内存中。而不需要等到号段用尽的时候才去更新号段。这样做很大程度上的降低了系统的风险。
那么某个点
到底是什么时候呢?
这里做了一个实验,号段设置长度为step=10
,max_id=1
当我拿第一个ID时,看到号段增加了,1/10
当我拿第三个Id时,看到号段又增加了,3/10
Leaf
采用双buffer
的方式,它的服务内部有两个号段缓存区segment
。当前号段已消耗10%时,还没能拿到下一个号段,则会另启一个更新线程去更新下一个号段。
简而言之就是Leaf
保证了总是会多缓存两个号段,即便哪一时刻数据库挂了,也会保证发号服务可以正常工作一段时间。
通常推荐号段(segment
)长度设置为服务高峰期发号QPS的600倍(10分钟),这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响。
优点:
- Leaf服务可以很方便的线性扩展,性能完全能够支撑大多数业务场景。
- 容灾性高:Leaf服务内部有号段缓存,即使DB宕机,短时间内Leaf仍能正常对外提供服务。
缺点:
- ID号码不够随机,能够泄露发号数量的信息,不太安全。
- DB宕机会造成整个系统不可用(用到数据库的都有可能)。
二、Leaf-snowflake
Leaf-snowflake
基本上就是沿用了snowflake的设计,ID组成结构:正数位
(占1比特)+ 时间戳
(占41比特)+ 机器ID
(占5比特)+ 机房ID
(占5比特)+ 自增值
(占12比特),总共64比特组成的一个Long类型。
Leaf-snowflake
不同于原始snowflake算法地方,主要是在workId的生成上,Leaf-snowflake
依靠Zookeeper
生成workId
,也就是上边的机器ID
(占5比特)+ 机房ID
(占5比特)。Leaf
中workId是基于ZooKeeper的顺序Id
来生成的,每个应用在使用Leaf-snowflake时,启动时都会都在Zookeeper中生成一个顺序Id,相当于一台机器对应一个顺序节点,也就是一个workId。
Leaf-snowflake
启动服务的过程大致如下:
- 启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下检查自己是否已经注册过(是否有该顺序子节点)。
- 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。
- 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。
但Leaf-snowflake
对Zookeeper是一种弱依赖关系,除了每次会去ZK拿数据以外,也会在本机文件系统上缓存一个workerID
文件。一旦ZooKeeper出现问题,恰好机器出现故障需重启时,依然能够保证服务正常启动。
启动Leaf-snowflake
模式也比较简单,起动本地ZooKeeper,修改一下项目中的leaf.properties
文件,关闭leaf.segment模式
,启用leaf.snowflake
模式即可。
leaf.segment.enable=false
#leaf.jdbc.url=jdbc:mysql://127.0.0.1:3306/xin-master?useUnicode=true&characterEncoding=utf8
#leaf.jdbc.username=junkang
#leaf.jdbc.password=junkang
leaf.snowflake.enable=true
leaf.snowflake.zk.address=127.0.0.1
leaf.snowflake.port=2181
/**
* 雪花算法模式
* @param key
* @return
*/
@RequestMapping(value = “/api/snowflake/get/{key}”)
public String getSnowflakeId(@PathVariable(“key”) String key) {
return get(key, snowflakeService.getId(key));
}
测试一下,访问:http://127.0.0.1:8080/api/snowflake/get/leaf-segment-test
优点:
- ID号码是趋势递增的8byte的64位数字,满足上述数据库存储的主键要求。
缺点:
- 依赖ZooKeeper,存在服务不可用风险(实在不知道有啥缺点了)
三、Leaf监控
请求地址:http://127.0.0.1:8080/cache
针对服务自身的监控,Leaf提供了Web层的内存数据映射界面,可以实时看到所有号段的下发状态。比如每个号段双buffer的使用情况,当前ID下发到了哪个位置等信息都可以在Web界面上查看。
总结
对于Leaf具体使用哪种模式,还是根据具体的业务场景使用,本文并没有对Leaf源码做过多的分析,因为Leaf 代码量简洁很好阅读。
#####大家看完有什么不懂的可以在下方留言讨论
#####也可以关注.谢谢你的观看。
#####觉得文章对你有帮助的话记得关注我点个赞支持一下!
链接:https://juejin.im/post/6858063069000499208
1200页Java架构面试专题及答案
小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞
百度、字节、美团等大厂常见面试题
实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**