NotFound9

Results 8 issues of NotFound9

美团的同学: 你们好!针对https://github.com/Meituan-Dianping/Leaf/issues/72 我进行了进一步的优化,我提的PR地址是是https://github.com/Meituan-Dianping/Leaf/pull/102,感谢你们抽出时间进行查看! SegmentIDGenImpl.updateCacheFromDb()方法 原方案工作流程: 1.遍历cacheTags,将dbTags的副本insertTagsSet中存在的元素移除,使得insertTagsSet只有db新增的tag 2.遍历insertTagsSet,将这些新增的元素添加到cache中 3.遍历dbTags,将cacheTags的副本removeTagsSet中存在的元素移除,使得removeTagsSet只有cache中过期的tag 4.遍历removeTagsSet,将过期的元素移除cache 这种方案需要经历四次循环,使用两个HashSet分别存储db中新增的tag,cache中过期的tag, 并且为了筛选出新增的tag,过期的tag,对每个现在使用的tag有两次删除操作, 原有方案代码如下: ``` List dbTags = dao.getAllTags(); if (dbTags == null || dbTags.isEmpty()) { return; } List cacheTags = new...

你好,就是每次机器启动后会去zookeeper中获取workId列表,判断当前IP+端口是否存在workId,如果有就使用这个workId,并且对该workId上次上报的最大时间戳与当前时间戳比较,如果是当前时间戳较小,那么抛出异常,以此来应对启动时时间回拨的问题,如果启动时连接zookeeper失败,会去本机缓存中读取workerID.properties文件,读取workId进行使用,但是由于workerID.properties中只存了workId信息,没有存储上次上报的最大时间戳,所以没有进行时间戳判断,所以如果机器的当前时间被修改到之前,就可能会导致生成的ID重复,这个问题是否需要进行修复,可以给你们提PR吗?每次在上报时间戳时将时间戳同时写入本机缓存,或者是在启动时连接zookeeper失败时不使用本机缓存,直接抛出异常。

美团的同学,你们好! 很感谢你们开源了Leaf框架,为分布式唯一ID生成提供了一种稳定可靠的解决方案,通过阅读源码,我也学到了很多。在看issue中[#84 workid是否支持回收](https://github.com/Meituan-Dianping/Leaf/issues/84)这个问题时,我也在仔细思考,由于业务的不同,还是有一些项目存在对workId复用的需求的,所以我fork了项目,然后在不影响之前的每个IP+Port对应一个固定的workId的机制下,增加了一种对workId循环复用的机制。主要实现原理如下: 默认情况时或者是WorkIdMode为PERSISTENT时, workId还是跟之前的一样,每个IP+Port对应一个固定的workId,SnowflakeIDGenImpl使用的holder是SnowflakeZookeeperHolder的实例 ``` IDGen idGen = new SnowflakeIDGenImpl(properties.getProperty("leaf.zk.list"), 8080); IDGen idGen = new SnowflakeIDGenImpl(properties.getProperty("leaf.zk.list"), 8080, WorkIdMode.PERSISTENT); ``` 如果WorkIdMode为RECYCLABLE时, 此时的workId是可循环利用的,那么SnowflakeIDGenImpl使用的holder是RecyclableZookeeperHolder的实例,工作流程如下: 1.首先会在未使用的workId池(zookeeper路径为/snowflake/leaf.name/recycle/notuse/)中生成所有workId。 2.然后每次服务器启动时都是去未使用的workId池取一个新的workId,然后放到正在使用的workId池(zookeeper路径为/snowflake/leaf.name/recycle/inuse/)下,将此workId用于Id生成,并且定时上报时间戳,更新zookeeper中的节点信息。 3.并且定时检测正在使用的workId池,发现某个workId超过最大时间没有更新时间戳的workId,会把它从正在使用的workId池移出,然后放到未使用的workId池中,以供workId循环使用。 4.并且正在使用这个很长时间没有更新时间戳的workId的服务器,在发现自己超过最大时间,还没有上报时间戳成功后,会停止id生成服务,以防workId被其他服务器循环使用,导致id重复。 ``` IDGen idGen =...

在[Leaf的官方介绍文章](https://tech.meituan.com/2017/04/21/mt-leaf.html)中曾经提到分布式ID应该保证信息安全性, >4.信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。 ![image](https://user-images.githubusercontent.com/16741621/84752324-30905a80-aff0-11ea-8bb4-2fc0b781cc3a.png) ![image](https://user-images.githubusercontent.com/16741621/84753580-c2e52e00-aff1-11ea-9e7f-389c962ed54a.png) 让ID不连续,否则容易被恶意爬取和泄露单量,目前使用snowflake模式生成ID时是有取随机数相关的逻辑来保证ID不连续的,但是如果是Leaf-segment数据库方案来生成ID,每次从数据库取完ID,都是存储在内存中,发放给业务项目,所以运行期间,使用的ID都是连续的,竞争对手很容易通过在两天中午12点分别下单,通过订单id号相减就能大致计算出公司一天的订单量。如果我们在每次从数据库取一个分段的ID时,计算一个随机数,丢弃掉随机数数量的ID,这样就可以保证ID不连续,保证Leaf-segment数据库方案来保证生成ID的安全性。 源代码:SegmentIDGenImpl中updateSegmentFromDb()方法中计算当前ID分段最小值 ```java long value = leafAlloc.getMaxId() - buffer.getStep(); ``` 修改后的代码 ```java int bound = buffer.getStep()/20;//随机值最大取值为5%的Step,主要考虑到buffer中id使用量超过10%就会触发另一个buffer的更新,所以我们取的随机值的最大值小于10%会好一些,不然一开始就触发更新了。 int randomValue = RANDOM.nextInt(bound);//生成随机值 long value = leafAlloc.getMaxId() - buffer.getStep()...

因为Leaf框架是沿用snowflake的位数分配, ![image](https://user-images.githubusercontent.com/16741621/80939338-efacff80-8e0e-11ea-99d4-d90484f09248.png) 最大41位时间差+10位的workID+12位序列化,但是由于snowflake是强制要求第一位为符号位0,否则生成的id转换为十进制后会是复试,但是Leaf项目中没有对时间差进行校验,当时间戳过大或者自定义的twepoch设置不当过小,会导致计算得到的时间差过大,转化为2进制后超过41位,且第一位为1,会导致生成的long类型的id为负数,例如当timestamp = twepoch+2199023255552L时, 此时在生成id时,timestamp - twepoch会等于2199023255552,2199023255552转换为二进制后是1+41个0,此时生成的id由于符号位是1,id会是负数-9223372036854775793 ``` long id = ((timestamp - twepoch)

美团的同学: 你们好!这个PR主要是针对https://github.com/Meituan-Dianping/Leaf/issues/72 进行了进一步的优化,感谢你们抽出时间进行查阅。 SegmentIDGenImpl.updateCacheFromDb()方法 原方案工作流程: 1.遍历cacheTags,将dbTags的副本insertTagsSet中存在的元素移除,使得insertTagsSet只有db新增的tag 2.遍历insertTagsSet,将这些新增的元素添加到cache中 3.遍历dbTags,将cacheTags的副本removeTagsSet中存在的元素移除,使得removeTagsSet只有cache中过期的tag 4.遍历removeTagsSet,将过期的元素移除cache 这种方案需要经历四次循环,使用两个HashSet分别存储db中新增的tag,cache中过期的tag, 并且为了筛选出新增的tag,过期的tag,对每个现在使用的tag有两次删除操作, 原有方案代码如下: ``` List dbTags = dao.getAllTags(); if (dbTags == null || dbTags.isEmpty()) { return; } List cacheTags = new...

因为简介栏这里是英文的介绍,首页ReadMe.md也是英文介绍,这样在Github搜索“分布式id”时,即便Leaf框架是Star最多的,都不会显示在列表,建议将简介改为: **Distributed ID Generate Service 分布式ID生成系统** 这样在Github搜索”分布式id“等一些中文搜索词时就可以搜到Leaf项目了,这样可以提高项目曝光率 ![image](https://user-images.githubusercontent.com/16741621/79711328-20af0f80-82fa-11ea-879c-c46ba4eae973.png) ![image](https://user-images.githubusercontent.com/16741621/79711506-90bd9580-82fa-11ea-8cc2-40228d717aad.png)

能否增加动态step调整,因为如果一开始对业务调用量无法评估的话,对step设置的过小会导致每次分配的segement使用过快,更新时冲突的概率变大,设置得过大又容易造成segement浪费。如果在增加maxId时记录增加时间lastTimeStamp,在下次增加maxId时,判断当前时间减去lastTimeStamp之间的时间差,如果小于我们设定的时间间隔(例如15分钟),那么我们就增大内存中step变量的值,如果大于就适当减少step变量的值,这样可以让segment分配的频率在我们可控的氛围内,如果可以增加的话,我可以实现这部分代码提PR