1
xiaofan2 2023-06-05 17:57:35 +08:00
你们的 id 是 long 类型的吗?如果是 long 类型的话为什么要 hash ?
|
2
ben548 OP @xiaofan2 是 long 类型,目前设计不是用 hash ,考虑用 hash 是想着 100w 的 string key-value 数据内存占用应该是大于一个 100 万 key-value 的 hash 数据的(没做测试,只是靠印象和经验)
|
3
nicreve 2023-06-05 18:08:54 +08:00 1
Murmur 也没有这么吃性能吧,为什么不每次都实时计算而是要存在 Redis 里呢?如果单纯为了 ID 分布均匀,还有很多比 Murmur 更快的非标 Hash 算法,反正这个场景也不在乎 Hash 冲突。
|
4
matrix1010 2023-06-05 18:13:04 +08:00
value 是什么, 每个用户都不一样吗?
|
5
octobersnow 2023-06-05 18:16:06 +08:00
每次都 hash ,不用存 redis
|
6
ben548 OP @nicreve 因为需要记录是不是第一次生成,只有第一次分配桶,才触发同步数据部门,我需要记录这样一个是否已经分配过的状态,来判断是否需要同步分桶结果给到数据部门
|
7
ben548 OP @matrix1010 就是 0 ,1 ,2 ,3 这种数字,分到对应桶的用户都是一个 value
|
8
ben548 OP @octobersnow 因为需要记录是不是第一次生成,只有第一次分配桶,才触发同步数据部门,我需要记录这样一个是否已经分配过的状态,来判断是否需要同步分桶结果给到数据部门
|
9
nicreve 2023-06-05 18:24:25 +08:00
@ben548 问题是不是搞复杂了,你和数据部门的 Hash 及分桶规则保持一致不就可以了么,不需要进行同步啊。别告诉我你们的数据部门只会写 SQL ,这种基本的工程能力都没有?
|
10
ben548 OP @nicreve 目前是需要同步给他们的,我理解是这样会更好一些吧,因为这样数据部门不与业务绑定,相互隔离会是更好的设计吧,不然我们这边的规则改了,他们也要跟着一起改吗?很多时候没有及时通知容易出问题
|
11
seth19960929 2023-06-05 18:27:27 +08:00
上策: 让数据部分自己判断是否同步过
中策: 别存分组, 实时计算, 用个 bitmap 来记录是否同步过 下策: 代码能跑. 百万级你怕什么. 千万级的 hash 都见过 |
12
cloudzhou 2023-06-05 18:28:45 +08:00
在维护 key 数量和足够分散做一个均衡就好了:
1. murmurhash(uid) % 4 = 分桶信息 2. murmurhash(uid) % 1024 = 分桶信息存储的 key |
13
awalkingman 2023-06-05 18:49:44 +08:00
key:user_id ,value:1|2|3|4. 不用 hash 或者别的容器,有记录就是分完的,没记录就是没分过的。就当数据库用好了,不是大 key ,就算几千万个 key 也能跑就是耗点空间而已。
删除是异步删的,但是删大 key 会影响性能(也就是阻塞)。 或者直接放 db ,根据主键查一个字段,也是 10ms 以内的时间。 |
14
ben548 OP @cloudzhou 这个差不多就是我的想法了,第二次做我应该会直接存 hash 里面,然后再做分片,晚点去写个测试案例,来试试是不是用 hash 存储会比用几十万个 string 存更省内存
|
15
ben548 OP @awalkingman big key 还是不太建议的,带来的不仅仅是 getall 的 O(n)操作导致的阻塞问题还有很多其他的问题,要用 hash 还是会考虑分片
|
16
ben548 OP @seth19960929
中策 bitmap 的方案有一个比较大的弊端,如果 userid 不是那种连续递增的类型,会导致大量空间浪费,目前我们的用户 id 是雪花算法生成的 18 位长 id ,我感觉不太适合用 bitmap 了 下策的方案 big key 还是不太建议的,带来的不仅仅是 getall 的 O(n)操作导致的阻塞问题还有很多其他的问题,要用 hash 还是会考虑分片 |
17
blessingsi 2023-06-05 21:02:29 +08:00
不管是 hash 还是 bitmap 都分片存就行了吧
|
18
worldOnlyYou 2023-06-05 23:07:11 +08:00
百万 key 应该还好,每个 key 也不大。换成 hash 的话,除了能节省点内存,如果后期有性能问题,不是很好解决(扩分片没有效果)
|
19
worldOnlyYou 2023-06-05 23:08:29 +08:00
定时删除是在主进程上完成,如果过多的 key 失效,redis 会有定时机制。印象中是最多 10ms?
|
20
xuanbg 2023-06-06 02:59:56 +08:00
取个模而已,为什么还要存起来?
|
21
awalkingman 2023-06-06 09:30:00 +08:00
@ben548 是 many key 不是 big key
|
22
ben548 OP @awalkingman 百万级别的 hash 不是 big key 吗?我理解是的,big key 和 many key 是怎么划分的呢
|
23
awalkingman 2023-06-06 10:55:14 +08:00
@ben548 我的意思是,每个 key 内容是用户 id ,value 就是这个用户的分桶数值。不用套进 hash 或者其他集合容器,这样就会有数百万个 key ,就是最基本的 key:value
|
24
tsutomu 2023-06-06 11:27:36 +08:00
我们部门代码都是 key_uid 这样拼成的 key ,最多能有几千万。hash 是不让用的,太大了,很容易触发读写频控,好像还会导致打在一个实例上导致负载不均衡啥的,这个就不清楚了。
|
25
ben548 OP @tsutomu 对的,这些都是 big key 的坏处,然后也不是不可以解决,hash 分片就行,分的足够碎就不会有这样的问题了
|
26
fivesmallq 2023-06-06 12:52:55 +08:00
一般来说都是不记录的,client sdk 直接算,提供好统一的 sdk ,或者你们提供 api ,server 计算就可以。 每次同步给他和他直接拿结果没有太大区别。可以看看几个开源的 ab test 项目的实现,有的用的是 MurmurHash 有的是 FNV
https://github.com/Unleash/unleash/issues/247 https://docs.growthbook.io/lib/build-your-own#hashseed-string-value-string-version-integer-floatnull |
27
Masoud2023 2023-06-06 17:39:48 +08:00
我最近总觉得取模这个东西不太好...如果某天突然要分成 5 个就要涉及到一个重新分区的问题...到时候就.爽了
|
28
BQsummer 2023-06-06 18:00:39 +08:00
abtest 大部分是入组不出组的, 所以要记录入组信息, 方便下次进的还是同一个组. 我们公司就是 map 存的, key 是 uid, 可能是用户量不大, 日活才 60w, redis 扛得住.
|
29
seth19960929 2023-06-07 10:11:55 +08:00
@ben548 按 userid 尾号切分
|