MongoDB 怎么做可变 field 冷热数据自动 sharding?

2015-08-04 18:40:21 +08:00
 mengzhuo
sharding之后就不能更新了……
有什么好办法吗?
5346 次点击
所在节点    MongoDB
18 条回复
minvacai
2015-08-04 21:13:07 +08:00
可变field冷热数据自动sharding是什么意思啊,sharding不是根据shard key来的吗?
mengzhuo
2015-08-04 21:54:55 +08:00
@minvacai
比如有一个field 叫 last_login ,用户登入之后变更到现在的时间
按这个last_login 进行shard
minvacai
2015-08-04 22:41:54 +08:00
首先,原则上来说你不应该选这个来作shard key,因为很显然这会导致某个分片服务器成为热点(hot spot)

其次,MongoDB手册里有一句The shard key is either an indexed field or an indexed compound field that exists in every document in the collection.换句话说,既然是索引,插入了以后显然就不能更新的。

shard key是用来确定一个文档存放在哪一个shard上的,设计的时候的考虑,一是要有足够大的基数,可以把要分配到各片的数据块划分得足够小或者说均匀,二是在分片后使得访问压力能尽量平摊到各分片服务器上,从这一点来说,用时间是不合适的
mengzhuo
2015-08-05 00:00:53 +08:00
@minvacai 主要是因为要冷热数据进行分离
冷数据被访问的可能性很低 所以想用磁盘大 但性能不是很好的机子跑
官方也有相关的帖子 但是一旦登入时间shard之后就不能改变了
刚才在so上有个哥们说可以用movechunk来移动数据但是我发现那也是一段chunk挪动
我之前用uuid shard的 所以指不定那段chunk里有热数据…
minvacai
2015-08-05 00:09:32 +08:00
但是这样你做,一旦并发量大的时候性能就捉鸡了吧
而且难道你要自己管理分块吗
pixstone
2015-08-05 01:59:12 +08:00
首先 冷热数据分离 用shard 来做并不合理。shard,一般是用来处理单机内存,不足以放下 MongoDB的热数据(含索引)的时候才采用的。如果是用户基础数据的话,并不大量吧?冷数据系统会自动清出内存的。

关于题主的真实需求是啥?让用户热数据在好的机子上,来加快用户相关接口的访问速度还是啥?
vietor
2015-08-05 07:56:53 +08:00
用cache做假冷热,可以降mongo服务器配置了
mengzhuo
2015-08-05 10:08:21 +08:00
@minvacai
@pixstone

是这样的,开发的是手游
用户的特点是:一旦不玩了,就很有可能到关服那天都不会再用了。
但是,相对的,活跃玩家会非常频繁地读写,领导的意思是,常用操作,比如加加金币之类,包括逻辑服务器操作,都必须在30ms之下。

所以,最初我想用sharding来把活跃用户统统塞到一台用RAMdisk跑的mongodb上。
现在发现貌似不行了……
mengzhuo
2015-08-05 10:09:22 +08:00
@vietor

光用cache做冷热就是目前的架构了
但是取批量用户信息时就嗝屁了,因为要请求多次redis
jiangzhuo
2015-08-05 10:19:24 +08:00
@mengzhuo 请求一次Redis不行吗?
如果偏要用sharding的话 用lastLogin做片键然后自己手动实施分片策略和移动chunk就是了,不过在移动chunk的时候查询效率 我觉得可能难以保证30ms内完成你的逻辑
解决冷热数据有很多方法啊,这样折腾值不值得呢
pixstone
2015-08-05 10:21:52 +08:00
@mengzhuo 这个你就不用担心了,内存中的数据如果很久没使用就会释放了,mongodb的内存管理都推给系统来做了。至于什么时候释放看 系统自己了。在内存中的基本都是热数据,只要内存中能放下 热数据和索引就足够了。
之前项目是亿级的记录,全部数据百G,内存常驻热数据9G左右。
然后 前面提到到的 30ms 要求。建议根据各个链路的日志信息监控下各个流程的消耗 再来针对性优化。直接就到数据库层优化有点早了。如果是mongodb在拖后腿的话,大概消耗了多久?什么操作?读取还是写入。

对了,额外说下 mongodb 的写性能一般,相对于轻松上万 qps 的读来说,而且写会影响读性能。使用主从来实现简单的读写分离也是 题主 可以考虑优化的选项之一。
mengzhuo
2015-08-05 10:34:49 +08:00
@jiangzhuo

不行……因为每个玩家的属性是要实时更新的,类似于JOIN操作
比如我和你是好友,每次我列出好友列表时,你的属性值(存档数据)也需要列出来的

移动chunk时,移出的服务器还是正常工作的,效率还是有保证的。

这么折腾就是为了把mongodb用到极致(个人的习惯:把东西用到极致),这样还不行再上redis
fds
2015-08-05 10:40:46 +08:00
@mengzhuo RAMdisk有必要么…… mongo不是号称自动把热数据放在内存里么,冷数据本来就应该在硬盘上吧。怀疑是不是index太大了?那应该考虑减少document数量,每个玩家尽可能10个document以内。
mengzhuo
2015-08-05 10:51:43 +08:00
@pixstone

好的,我先继续写逻辑好了,反正sharding之后也可以加索引

不过亿级数据百G,我们500w就已经750G了
按领导的意思,这个新项目至少每个大区服都有1000W玩家

读写效率的话,我们用mongopref测试过

{ nThreads: 16, fileSizeMB: 500, r: true, w: true }

一般HDD: 107 ops/sec 0 MB/sec
aws SSD: 3059 ops/sec 11 MB/sec
RAMdisk: 431460 ops/sec 1685 MB/sec

根本不在一个等级上啊……
pixstone
2015-08-05 10:57:48 +08:00
@mengzhuo 俺们的数据超级扁平,所以仅仅量大。

那个测试结果的话...不太清楚呢
wupher
2015-08-05 13:46:08 +08:00
冷热数据拆分与数据库横向扩展这两个机制不应该混于一处处理比较好吧。

要我的话,宁可写个脚本,在闲时单独做冷热数据分离,视场景移动至另外一个Collection甚至database中。
wengyuchen
2015-08-05 17:22:11 +08:00
不如上Replica set架构,开读写分离.定期清理长期不登录的账户.
这么早折腾sharding运维成本得不偿失.而且sharding本意并不是这样用的.
mengzhuo
2015-08-05 19:23:19 +08:00
@wengyuchen

不登入的也不能清啊…因为没准他的好友是活跃用户
读写分离是shard之前肯定要上的了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/210775

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX