1
wfd0807 2018-05-07 18:43:55 +08:00 1
少见多怪
|
2
snal123 2018-05-07 19:02:44 +08:00 via iPhone
可能只是存了一点缓存吧 方便读取,重要的还是存在 mysql 里?
|
3
eslizn 2018-05-07 19:11:15 +08:00 1
redis 本身就是持久化存储,没毛病的,性能也高。要说唯一的缺点就是管理和数据提取麻烦点
|
4
rrfeng 2018-05-07 19:12:13 +08:00 via Android
Redis 的持久化是不安全的。
要这么用为什么不直接上个 MongoDB ... |
5
AltairT 2018-05-07 19:13:26 +08:00 via iPhone
赞同二楼,不知 po 主是怎么用 redis 的🧐
|
6
dltsgl 2018-05-07 19:19:43 +08:00
查询不方便吧,比如根据手机号查用户之类
|
7
whatisnew 2018-05-07 19:21:19 +08:00
涉及到事务就悲催了
|
8
cout2013mr 2018-05-07 19:23:24 +08:00 via Android
赞同二楼
|
9
hand515 2018-05-07 19:26:05 +08:00
id 查询还好,O ( 1 ),问题是按条件筛选,每次都是 O ( N )吧
|
10
kindjeff 2018-05-07 19:27:46 +08:00 via iPhone
redis 不就是这么用的吗
|
11
johnsneakers OP 尴尬了原来我才是非主流
|
12
Zzde 2018-05-07 19:35:04 +08:00 via iPhone
当缓存用不是很正常吗。
我经常这样用..... |
13
wizardforcel 2018-05-07 20:05:55 +08:00 via Android
我的话会申请个 mongodb 再这么玩😂😂
|
14
quxiangxuanqxx 2018-05-07 22:48:03 +08:00 via Android
呃………缓存不是这样吗? redis 搞缓存这样用不对吗………
|
15
wdlth 2018-05-07 22:53:20 +08:00
如果是用于缓存,没什么问题,取一部分信息进行缓存预热。
|
16
reself 2018-05-07 22:55:06 +08:00 via Android
不然呢?难道你把 session 放 MySQL ?
|
17
changnet 2018-05-07 22:59:52 +08:00 via Android
redis 做缓存不是很正常吗。只是做持久化在稳定性,容灾,可维护性不如 mysql,很多工具不如 mysql。才 10000 数据,这个很少啊。
|
18
troywinter 2018-05-07 23:55:45 +08:00
看 value 的大小,value 过大的话,redis 在并发量高时的性能就是灾难,具体看阿里的 redis 编程规范。
|
19
suit 2018-05-08 00:39:33 +08:00
刚学 redis 的时候试过只用 redis 做持久层写一个商城,然后碰到多对多的关联就懵逼了,而且一些逻辑上相关的 key 还得用另一个 hash 来记录,数量一多就很难管理
|
20
johnsneakers OP @eslizn 我有点懵逼了, 虽然还没有上线, 但是把几十万用户信息存到一个 hash 里面是大家公认最好的做法吗?
@Zzde @quxiangxuanqxx @reself @changnet 不是缓存,详见 append |
21
Los 2018-05-08 01:15:59 +08:00
@johnsneakers 是的,这样做没有太大问题。你只是潜意识里信不过 redis 而已。。
|
22
changwei 2018-05-08 01:24:03 +08:00 via Android
hashtable 里面放一百万个 key 有什么不对吗? hashtable 的查找时间复杂度是 o ( 1 )的(当然排除 hash 冲突的情况),和数据量又无关,只要内存够大,你放一千万个也没什么问题啊。
|
23
changwei 2018-05-08 01:28:19 +08:00 via Android
@dltsgl 那就再做一个手机号到 uid 的 key-value 对呗! redis 建缓存就像 mysql 建索引的策略一样,哪个是索引项就对谁建缓存。
|
24
kran 2018-05-08 08:30:09 +08:00 via iPhone 1
|
25
hareandlion 2018-05-08 08:40:54 +08:00 via Android
貌似很多人都觉得 Redis 不能做持久化存储
|
26
realpg 2018-05-08 08:48:22 +08:00
|
27
owt5008137 2018-05-08 08:49:55 +08:00 via Android 1
不考虑 sharding 或者自己做 sharding 是可以这么做。
但是别听上面他们说的,你的做法是对的。现有的 redus 的 sharding 方案全是基于 key 的,所有的数据存一个 key 那就只能单点。而且一级 key 带 uid 这样二级还可以再分字段,可以实现只存脏数据字段和读取部分字段,能减少很多 redis 压力的。 |
28
agostop 2018-05-08 08:55:54 +08:00
赞同#27,等到数据量上来,需要切片的时候,你就发现,傻了……
不过对于功能来讲,没什么问题。 |
29
lepig 2018-05-08 09:09:37 +08:00
功能上没什么问题 只是分 key 方便写代码和管理
|
30
salamanderMH 2018-05-08 09:10:13 +08:00
全部存一个 key,这个还是不寻常的
|
31
suyuanhxx 2018-05-08 09:32:16 +08:00
没什么太大问题,redis hash 结构-》 key field(hashkey) value,虽然是同一个 key,但是不同的 hashkey,没问题,但是这种方式不太优雅
|
32
kiddult 2018-05-08 09:46:16 +08:00
这里面大部分人的用户只有几十几百么?一个 hash 放这么多内容,你是打算找死呢,还是想害死 redis 运维?这么大 key 线上要出事的,楼主的做法才明明是对的
|
33
ryanking8215 2018-05-08 09:48:25 +08:00
记得哪里看到过,有公司(instagram ?)使用 key-value 方式存储觉得太占空间,咨询 redis 开发组后,改成 hash 方式存储,节约空间。
|
34
ylcc 2018-05-08 09:54:30 +08:00
为什么这么多人觉得一个 key 存这么大的数据没问题啊,这么干肯定需要拆分一下啊。
|
36
windstill 2018-05-08 10:04:10 +08:00 1
之前看过一篇 redis 优化的文章,其中说到一级 key 的数量不能太多。你那样一个用户一个 key,几百万个一级 key,会影响 redis 的读写效率。
不知道其他大神怎么看 |
37
g8287694 2018-05-08 10:12:01 +08:00
阿里的 redis 使用手册了解一下
|
38
eslizn 2018-05-08 10:13:25 +08:00
@johnsneakers 一个 hash key 里确实有问题,之前审题没注意,以为是一个用户一个 hash,里面存属性
|
39
mingzu 2018-05-08 10:14:01 +08:00 2
看了上半段回复开始自我怀疑人生了..
还好后半段回复又把我抓回来了。。 |
40
eslizn 2018-05-08 10:15:07 +08:00
@johnsneakers 因为一个 key 的话没办水平扩展,无法利用集群
|
41
limitsy 2018-05-08 10:18:49 +08:00
看懂了。。意思就是。hash 作为一张表用?社会社会。。
|
42
jyf 2018-05-08 10:20:20 +08:00
这样做其实挺好的 我记得 instgram 还是 flickr 曾经分享过一个心得 是把他们的数据从你那种方式转换成提问里这种方式 内存省了好多好多
另外你没想到这样清理方便么 |
43
mentalidade 2018-05-08 10:29:01 +08:00
跟我这个很像,不过我不要哈希,就 key-value,/t/450596
|
44
myyou 2018-05-08 10:30:48 +08:00
用 hash 据说可以让内存使用减小到是 string key 的 1/10,而且 hash 的查询速度也很快。现在的 redis 已经很稳定了,架构设计合理,作为很持久化使用,并没有什么不妥。
|
45
jyf 2018-05-08 10:31:25 +08:00
|
46
OneNian 2018-05-08 10:34:17 +08:00 via iPhone
居然有人觉得一个 hash 这样用很合理,持久化也很合理?……用过 redis 没?
|
48
tylerdurden 2018-05-08 10:39:11 +08:00
既然都是程序员,咱们数据说话好不好,来个对比呗,不要臆断可以么
|
49
changnet 2018-05-08 10:43:32 +08:00 via Android
@johnsneakers 没说这是最好的方案啊,具体业务不知道,你们项目成员经验也不知道,不好说。通常都是 redis 做缓存,后面 mysql 落地。一个 key 的问题,这个设计有点奇怪,一般都是分开的吧。
|
50
youxiachai 2018-05-08 10:45:55 +08:00
@changnet redis 其实也能做落地...
人家实践过.应该是信得过,redis 的落地 |
51
gotanaka4869 2018-05-08 10:48:40 +08:00
|
52
changnet 2018-05-08 10:49:24 +08:00 via Android
@youxiachai 是能做落地。但是实际操作起来团队的经验不够,运维的经验不够,容灾不如 mysql 成熟,不好做。还要考虑后续优化,维护啊。
|
53
youxiachai 2018-05-08 10:49:56 +08:00
|
54
nooper 2018-05-08 10:50:23 +08:00
|
55
9684xtpa 2018-05-08 10:51:06 +08:00
不过如果是集群的话,这么做会导致热点 key,然后并发高的话,会有问题的
|
56
imherer 2018-05-08 10:58:00 +08:00
这样做应该也没什么大问题吧
不过我的做法和你一样,也是一个 user 一个 key |
57
youxiachai 2018-05-08 10:58:48 +08:00
看了一下...instagram 那篇文章居然是 2011 年的....
一些...大厂的博客..还是值得去翻翻啊.. |
58
youxiachai 2018-05-08 11:06:57 +08:00
@ylcc 其实..instagram .. 2011 年就分享过这样的操作了......
|
59
darklowly 2018-05-08 11:08:01 +08:00 1
假设按照
users:id 的模式存储 那么 id 为 10000 的用户的存储 key 是: users:10000,key 大概需要 11 个字节 同时 id 为 10001 的用户的存储 key 是: users:10001,key 大概需要 11 个字节 如果是按照 hash 来存储 则两个用户,一共需要 len(users) + len(10000) + len(10001) = 5 + 5 + 5 = 15 个字节 依此类推。 @9684xtpa 如果是集群的话, 给 user 分片就可以了,例如 users_1,users_2 |
60
jwdstefani 2018-05-08 11:10:16 +08:00
这种玩法 直接上 mongo 啊
|
61
darklowly 2018-05-08 11:12:41 +08:00
同时注意几点
1 搞程序的严谨一点, 不要觉得自己没见过的,就不合理,就要喷一下。 2 适当的调查一下,或搜索一下就能解决的问题,不要拿来喷 3 标题党太严重,还是你自己真的十分大惊小怪? |
62
youxiachai 2018-05-08 11:19:54 +08:00
@darklowly 我觉得..应该是真的没见识过的吧...
毕竟 lz 还尝试.说服对方... |
63
bk201 2018-05-08 11:22:30 +08:00
hash 只会在额定的要求范围内,才会以 ziplist 存储,当超过额定阈值后会转换成真正 hashtable 格式并重新存储。而 hashtable 的存储对于内存的使用不占优势
== 你是说这个问题嘛 |
64
johnsneakers OP @darklowly
1. 你还挺会扣帽子的,我哪里喷了。不合理的设计提出来说怎么了? 2. 论坛不是讨论技术的地方? 设计上的东西发论坛来讨论怎么了? 又是一顶帽子? 3. 标题党? 我确实很惊讶。 你的分析也很有意思, 拿多个 key 存储方案和一个 key 存储方案来比容量。 |
65
johnsneakers OP @youxiachai 确实没见识过,所以发到论坛求教一下
|
66
perssy 2018-05-08 11:28:18 +08:00
@youxiachai 这篇文章里写的也不是把所有 key 都放一个 hash 里吧,而是每个 hash 存 1000 条数据,超过这个数字的话 HSET 会有明显的 cpu 占用
|
67
gouchaoer 2018-05-08 11:31:11 +08:00
我觉得 LZ 说的没错啊,redis 本质上是一个缓存,数据落地到数据库是理所当然的啊
最重要的是如果用户信息存到 redis 里面了,那么你只能根据用户 id 去存取而无法做查询操作,比如你要查询哪些用户今天登录过,redis 没法查询哦 另外推荐 mongo 的,这个场景有意义么? |
68
hyq 2018-05-08 11:41:55 +08:00
即使楼主 append 了一下,还是有不少人没看明白。
|
69
liu7833 2018-05-08 11:45:51 +08:00 1
一个 hash key 存的话肯定是有问题的,容易造成 key 的热点,最终打垮一个节点
|
70
troywinter 2018-05-08 11:53:22 +08:00
那些说放到 hash 里合理的,你们写个性能测试看看,不用说千万并发,就 10 万的并发,你们看看 redis 的性能
|
71
caixiexin 2018-05-08 11:53:30 +08:00 via Android
大 key 在 Redis 集群里是个隐患
|
72
ytmsdy 2018-05-08 11:59:54 +08:00
结合具体的业务实际情况吧,如果业务上对用户信息需要高频读写,那这么搞也算是情有可原。
但是想了一圈,想不出来能有什么业务需要对用户信息高频读写的。 打个比方 Redis 类似于微粒贷,花呗等短期的消费贷款 mysql 类似于房贷 偶尔手头紧,来点消费贷缓解燃眉之急,没问题。 但是要是拿着消费贷去买房子那就有点嘬死了 |
73
Waterchestnut 2018-05-08 12:01:42 +08:00
这种会有热 key 问题,节点会瘫痪,会报出 too many cluster redirections。。。。血的教训啊
|
74
enenaaa 2018-05-08 12:04:59 +08:00
从主楼内容看,楼主语文堪忧
|
75
ty89 2018-05-08 12:11:07 +08:00
@ytmsdy 游戏业务里对用户数据读写操作是很频繁的,比如战斗中计算战力值,经验点数的增加减少,装备对战力的加成影响等等,一堆高频读写。
楼主少见多怪且蜜汁自信,新人总是会认为老项目里各种做法不合理,直到自己掉进坑里了才会发现原来这么做都是有原因的。 |
76
darklowly 2018-05-08 12:14:04 +08:00 4
@johnsneakers
第一 你的原话是( 第一次见这样玩的 ,我太菜了,怎么给对方说都不听)。 注意这里的措辞 第一次见这样玩的 我太菜了 怎么给对方说都不听。 就算不是喷?也带着极大的负面情绪。 第二 技术类的问题,网络上有很多的资料,如果自己没见过的,不懂的,第一反应,应该是查资料,而不是惊叹,也不是到论坛上讨论。在你把所面对的技术问题本身搞清楚了,再来讨论比较好。附赠一篇文章给你( https://blog.csdn.net/danky/article/details/1370632 ) 第三 在 redis 里面,本身就是一个大的 hashmap,然后 hashmap 包含很多的 key==>val,同时这里的 val 可能有多种类型。当 val 是 hashmap 的时候,他的数据结构本身和 redis 的大 haspmap,并没有太大的不同。 获取一条数据的流程大概是: 1 从大的 hashmap 拿到 user 集合的小 hashmap O(1)级别 2 从小的 hashmap 拿到 user 的信息 O(1)级别 你的想法是一步就能拿到的,为什么要两步? 性能损失了 50%?其实完整的过程是: 1 发送命令给 redis 2 从大的 hashmap 拿到 user 集合的小 hashmap O(1)级别 3 从小的 hashmap 拿到 user 的信息 O(1)级别 4 返回数据 2 和 3 都是 O(1)级别, 相比 1 和 4 的时间,可能 5%都不到。那么性能是微乎其微的。 第四 我并不是倾向于把所有用户放到一个 key 里面,也不倾向于一定要分开放,具体问题具体分析。我只是想说两种方案都可以。 |
77
clippit 2018-05-08 12:18:43 +08:00 1
可以参考一下 https://redis.io/topics/memory-optimization
用 hash 存一堆 k-v 的用户信息是可以节约内存的,但是单个 hash 不能太大,需要手动分一分 |
78
youxiachai 2018-05-08 12:24:36 +08:00
@perssy 那文章是 3 亿用户.....
这里是个实践问题....而已 |
79
youxiachai 2018-05-08 12:26:25 +08:00
@perssy 打错是 3 亿图片信息...
|
80
ety001 2018-05-08 12:26:36 +08:00
我觉得得先把语文学好,完全没有看懂说的是什么意思。。。
|
81
johnsneakers OP |
82
jiangzhuo 2018-05-08 13:09:04 +08:00
100W 规模的级别这么用没啥问题吧
而且在实现某些需求的时候还更方便 比如说我要一次把这些用户数据全从 redis 里清掉 |
83
johnsneakers OP @darklowly 谢谢你给我科普这些基础知识
|
84
nooper 2018-05-08 13:23:29 +08:00
@youxiachai 我感觉是同一时间发的,居然你比我的快。
|
85
jerryt 2018-05-08 13:41:49 +08:00
@Waterchestnut 同样遇到过, 真的肠子都悔青了
|
86
fenglangjuxu 2018-05-08 13:51:34 +08:00
这么做是有点奇怪,但是也没啥特别的.
虽然我是第二种做法. |
87
perssy 2018-05-08 13:51:49 +08:00
@youxiachai 我想还是有点差别的,这贴里讨论的是两个问题:
1. 能否把用户信息保存在 redis 里 2. 能否把全部用户信息保存在一个 hash 中 从 append 来看,lz 纠结的是第二个问题,那么用这篇文章作为论据反驳就不适合了,因为就像文章中也提到的,一个 hash 中的 key 不建议超过 1000 个 |
88
watzds 2018-05-08 14:00:43 +08:00 via Android
我初学 redis 的时候就发现这个问题了,当时是分开了,似乎一般情况两种都行,没深究
|
89
luw2007 2018-05-08 14:06:04 +08:00
用户不到千万,单 key,或者单用户 key 都可以。
超过千万,单 key 是做不到的,单用户 key 要考虑 key 多问题。 |
90
luw2007 2018-05-08 14:19:23 +08:00
在讨论一下关于效率的问题, 两者操作都是 O(1)。所以查询速度相差无几。
底层结构上单个 key-> hashtable,单用户 key-> hashtable,两者数据结构并无区别。 单个用户 key 查找 db.hashtable 命中返回。 单个 key 查找 db.hashtable 命中 再次查询 key.hashtable 命中返回。 多出来的一次查询操作基本可以忽略掉。 |
91
shuax 2018-05-08 14:21:41 +08:00
基本操作,O(1)有什么问题?不然 hash 设计来干嘛的
|
92
youxiachai 2018-05-08 14:33:30 +08:00
@perssy 文章的例子是 3 亿信息规模....反过来说..1k 个 key 就能处理 3 亿信息...
你觉得..lz 提的几万的量..甚至百万.... 无论是 cpu 还是别的...就几十万甚至几百万的量.. 你想到这些是不是没考虑到实际? |
93
sampeng 2018-05-08 15:23:16 +08:00
原则上可以,但现实中不推荐使用。
优点: 1.足够快。不会蛋疼 io 问题。 2.其实逻辑和管理会复杂,其实是被关系型数据库惯坏了。算法足够 ok。结构很好的话其实没什么问题。而且会简化很多问题。如果对数据可用性不那么高,只用 redis 反而是简单可依赖的。所以具体问题具体分析 有两点问题: 1,内存问题。100 万用户放得下,500 万用户呢? 2,单点问题。如果是云类的主机,都有一定概率的当机。自己服务器就不用说了,冷不丁挂了怎么搞。还有服务器迁移的时候得把数据 flush 到硬盘上。确保所有数据都 flush 好了才能做。另外就算全部有持久化,加载的时候如果数据足够多。真的不是一会半会。你们能忍几分钟服务不可用的状态?。做分布式很不好搞,自行做 hash 和分片不是不可以,但都用了这么大一坨了,为何不直接在 mysql 中弄呢? |
94
Felldeadbird 2018-05-08 15:23:53 +08:00
你同事的设计没毛病啊,楼主你的方案也合理。 就看哪边业务在实际 存取中,更贴合业务。
有时候依据某个值,只取 1 点数据,和取 1 个数据,连带获取大量数据的区别。 |
95
tikiet 2018-05-08 17:25:30 +08:00
标题配合头像太有误导性了 ;)
|
96
daxiangxuezhang 2018-05-08 17:41:35 +08:00
看了标题以为是要分享什么 redis 新特性
|
97
daxiangxuezhang 2018-05-08 17:43:28 +08:00
存 hash 感觉也没什么太大的问题吧,一个 key 担心热点数据拖垮节点的话就多搞几个,keyName = user + mod(userId,n)就好了么~
|
98
Mirana 2018-05-08 18:19:19 +08:00
本身就是单线程的,hset 里所有的数据取出来用单独一个 key 并没有任何优化,反而污染了命名空间
|
99
RorschachZZZ 2018-05-08 18:23:34 +08:00
我也是 string 存用户信息。这个 key 感觉太大了
|
100
xiadada 2018-05-08 19:13:52 +08:00
@daxiangxuezhang mod 的做法并没有压榨干存储空间, 应该用 / 法, user:213 user:233 提取出来一个 user:2 然后 里面是 13 和 33
|