V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
dw2693734d
V2EX  ›  Go 编程语言

Golang 的 Map 可不可以存大量的数据?比如说几个 GB 的数据

  •  
  •   dw2693734d · 310 天前 · 6378 次点击
    这是一个创建于 310 天前的主题,其中的信息可能已经有所发展或是发生改变。

    因为 map 是 O(1)的,我想用来当 key value 数据库,快速查询一些数据。

    这样会不会有什么隐患问题?

    70 条回复    2023-07-01 09:25:11 +08:00
    zhaokun
        1
    zhaokun  
       310 天前 via iPhone
    服务器宕机数据丢失!为啥不用 redis ,有备份机制
    dw2693734d
        2
    dw2693734d  
    OP
       310 天前
    @zhaokun 宕机无所谓,我对这个没要求,只要查的快就行
    seers
        3
    seers  
       310 天前 via Android
    我怎么感觉这么大个对象你没写好优化直接 gc 掉了咋办
    wzw
        4
    wzw  
       310 天前 via iPhone   ❤️ 2
    可以的,单机的时候,比 redis 性能好太多了。 我用 goframe 的 gmap
    prenwang
        5
    prenwang  
       310 天前   ❤️ 1
    freecache 或者 bigcache , 不担心 GC , 简单实用
    hhjswf
        6
    hhjswf  
       310 天前 via Android   ❤️ 1
    内存够大吗
    matrix1010
        7
    matrix1010  
       310 天前   ❤️ 1
    几个 G 没什么压力,可能 GC 的时候会占些系统资源但是你都这样用了我估计机器配置不错,问题不大。而且数据库我理解不用考虑数据驱逐问题,所以也不需要 sync pool 之类的针对 alloc 的优化。另外 freecache 和 bigcache 都是缓存和数据库还是有一定区别的,而且没有范型
    opengps
        8
    opengps  
       310 天前   ❤️ 1
    没什么问题,甚至在高可用硬件的配合下几乎可以拿内存当硬盘用,只是风险永远都在,持久化的备份设计一定要有
    mdn
        9
    mdn  
       310 天前   ❤️ 2
    内存够大的话没问题,不过建议使用 LRU cache 做优化
    dw2693734d
        10
    dw2693734d  
    OP
       310 天前 via iPhone
    @hhjswf 64g 的
    dw2693734d
        11
    dw2693734d  
    OP
       310 天前 via iPhone
    应该够用
    elechi
        12
    elechi  
       310 天前
    用个内存 KV 数据库也行
    dayeye2006199
        13
    dayeye2006199  
       310 天前
    不在乎持久化和拓展性的话(比如数据量放大 10 倍),为什么不呢?
    ljt1096
        14
    ljt1096  
       310 天前
    你大概是想在内存里做个缓存吧,Map 里虽然可以放几个 G 的数据,但是不太推荐这么写,比如你缓存什么时候失效,替换算法,还有和数据库之间的一致性什么的,自己手动实现什么的太麻烦了,建议看看有没有什么合适的库或者组件拿过来直接用。当然只是自己写着玩玩就随意了。
    documentzhangx66
        15
    documentzhangx66  
       310 天前
    那些觉得语言内置 map 性能比 Redis 好的朋友,你们猜猜为啥大家要选择 Redis 、Mysql 甚至 Oracle 。
    ryd994
        16
    ryd994  
       310 天前 via Android
    你这样用的话,可能碰到 corner case 就歇菜了
    如果用 memcached 等设计就是为了 cache 的软件 /库的话,它们一般有可以限制缓存时间和大小的个参数,可以避免意外挤爆内存
    ccde8259
        17
    ccde8259  
       310 天前
    用 bigcache ,前人总是踩过一些坑才做了这些工作。主要有这几个优势:
    1. Zero GC 如果 map 有上万对象 GC 起来要命,通过 cacheShard 里 ringBuffer 避免 GC 扫对象
    2. FIFO 过期策略,省的处理淘汰跟溢出的问题
    3. 并发安全,给上分片读写锁
    ns09005264
        18
    ns09005264  
       310 天前
    @documentzhangx66 #15 为啥,可以简单讲讲吗
    Ericcccccccc
        19
    Ericcccccccc  
       310 天前
    没问题, 主要考虑几点:

    1. 多个机器数据怎么保持同步, 或者说有不一致会不会有什么问题
    2. 数据怎么推送更新到全部机器上, 依然需要考虑不同机器之前出现差异的问题.
    3. 机器如果重启怎么加载?
    x77
        20
    x77  
       310 天前
    这个需求不就是 HIVE 数据库么
    hhjswf
        21
    hhjswf  
       310 天前 via Android
    @documentzhangx66 单论性能肯定吊打了,redis 至少得多经历一个网络 io
    dw2693734d
        22
    dw2693734d  
    OP
       310 天前
    @ccde8259 只读的,一次性加载进来,然后只读
    cabing
        23
    cabing  
       310 天前
    找个包调用下~
    HankLu
        24
    HankLu  
       310 天前
    试试就知道了
    beijinglowb
        25
    beijinglowb  
       310 天前 via iPhone
    @documentzhangx66 历史遗留问题或者跟风呗,比 mysql 好的太多了,为啥那么多人用,还不是甩不掉
    ccde8259
        26
    ccde8259  
       310 天前
    @dw2693734d
    都是静态数据那完全没有线程安全问题
    那用 map 方案规避 GC 的话估计得靠 Arena 分配一下内存就是了
    用了 Arena 不被 GC 主要就关注一下会不会发生奇怪的内存泄露情况
    现代操作系统反正内存基本上有 Swap 都是用不完的,但 Swap 是福也是祸
    生产性能非预期就需要确定会不会因为 Swap 导致性能暴跌
    iseki
        27
    iseki  
       310 天前
    @documentzhangx66 这都不是一种东西比啥啊
    dw2693734d
        28
    dw2693734d  
    OP
       310 天前
    @ccde8259 我把 swap 都关掉了,感觉 64g 够用了
    ccde8259
        29
    ccde8259  
       310 天前   ❤️ 3
    然后是预期 hashmap 是 o(1)的,这么大的 map 就需要考虑是 key 量是多少,怎么分布。
    hash 方案会不会导致某个 bucket 聚集了大量的 entry 。
    如果 bucket 里面 entry 太多,由于 hash 冲突用的链地址法,会退化成 o(N),N 是 bucket 里 entry 数量。
    一次性放进去那么多数据会不会导致有未完成的扩容行为,冷起性能被拖累,需不需要 warm up 。
    读取是全随机还是有特定热点的,在 hashmp 的基础上再套 LRU ,同样 o(1)但是收缩常数会不会更快?
    IDAEngine
        30
    IDAEngine  
       310 天前
    可以,毫无压力
    Vegetable
        31
    Vegetable  
       310 天前
    当然没问题,启动时将大数据集加载到内存是很常见的操作,设计好数据结构别让数据膨胀太多就好。
    james122333
        32
    james122333  
       310 天前 via Android
    我写 demo 的时候也都是这样搞 外部服务再快都不会比内部存取快
    但正式时应该都不会这样搞 会怎么搞不告诉你
    djoiwhud
        33
    djoiwhud  
       310 天前 via Android   ❤️ 1
    @documentzhangx66

    内置 map 肯定比 redis 性能好。就凭 tcp 的 io 毫秒级耗时,就压根不用比。

    op 的问题要看业务场景。只要不出现雪崩,就没什么问题。
    standchan
        34
    standchan  
       309 天前
    没试过,但是你最好一开始就指定好 map 的大小。golang 中 map 的扩增是耗费性能。自己玩无所谓,生产环境的话估计你这个方案通不过评审吧。
    cokyhe
        35
    cokyhe  
       309 天前
    楼主的目的是 demo 不用装 redis 之类的
    并且这个大数据不会再改变&&不能被对方拿到吧?
    webcape233
        36
    webcape233  
       309 天前 via iPhone
    我最近做的项目也用到这种了,从 sqlite 数据库拿出来缓存起来,不过量比你小
    webcape233
        37
    webcape233  
       309 天前 via iPhone
    我用的 sync map ,
    dw2693734d
        38
    dw2693734d  
    OP
       309 天前 via iPhone
    @cokyhe 对的
    wheeler
        39
    wheeler  
       309 天前
    golang 里面似乎 map 的 bucket 是不会缩容的
    PVXLL
        40
    PVXLL  
       309 天前 via iPhone
    @documentzhangx66 不懂装懂
    wurenzhidi
        41
    wurenzhidi  
       309 天前
    yes
    koebehshian
        42
    koebehshian  
       309 天前
    性能不是和算法有关系,和语言有啥关系
    csfreshman
        43
    csfreshman  
       309 天前   ❤️ 1
    没问题,我们线上服务器 256G 内存,服务第一次启动加载个 50G 的数据,没问题,后续增量更新。
    phithon
        44
    phithon  
       309 天前
    并发处理好就行
    documentzhangx66
        45
    documentzhangx66  
       309 天前
    @ns09005264

    健壮的系统,需要的可不仅仅只是简单情况下的性能。

    还需要:

    1.复杂状况下依然较高的性能。

    2.可调试性。

    3.可维护性。

    4.健壮性。

    5.数据安全性、正确性、一致性。

    6.整套系统的易用性。

    7.整套系统的用法的一致性。

    等等。

    语言容器直接装数据,那都是上古用法了,在后来漫长岁月的工程实践中,考虑了以上问题,才发展成为专用的数据库,甚至为了保证系统用法的一致性,发明了 SQL 。
    documentzhangx66
        46
    documentzhangx66  
       309 天前
    @djoiwhud

    “只要不出现雪崩”。

    你随便找个交易场景,这样做试试。

    然后再猜猜看,为什么要发明数据库。
    documentzhangx66
        47
    documentzhangx66  
       309 天前
    @iseki

    你说对了。再深挖这个问题,你会收获更多知识。
    documentzhangx66
        48
    documentzhangx66  
       309 天前
    @hhjswf

    一套系统,就只考虑性能吗?

    想想万一程序崩了?
    documentzhangx66
        49
    documentzhangx66  
       309 天前
    @PVXLL

    在这个话题下,

    说说我有什么不懂?

    说说你比我懂什么?
    djoiwhud
        50
    djoiwhud  
       309 天前 via Android   ❤️ 2
    @documentzhangx66

    您犯了教条主义的问题。任何方案都要看实际需求。不是什么都需要搞一致性可靠性原子性强保证。

    有状态服务最普遍的游戏行业大内存缓存是挺普遍的。不是所有业务都是无状态的 http 服务。不是所有业务都要考虑进程挂了怎么办。进程都挂了,还能怎么办?

    凉拌。

    我说句不好听的话,您要么是偏执的某个领域的资深开发。要么是刚学些皮毛,还处于兴奋期的小白。至于是那种,我没兴趣。

    就算你是有千万种教材拿出来说这样子不严谨,你依然不能否定大量公司实际在工程中应用的方案。
    ysc3839
        51
    ysc3839  
       309 天前 via Android
    @documentzhangx66 redis 还要走网络通信,还是基于 TCP 协议的,我认为不会更快。而且许多 redis 客户端库都支持客户端缓存,redis 也支持 value 发生更改时通知客户端清除缓存。
    ysc3839
        52
    ysc3839  
       308 天前 via Android
    @documentzhangx66 我目前就在开发一个支持分布式的服务。客户端会与服务进程通信,服务进程从 redis 获取用户 session 信息,以及上报当前 session 的一些数据到 redis 。还有个管理进程去维护 redis 中的数据,最终数据都是存放在 mysql 中的。
    服务进程中有使用 map 进行 redis 数据缓存,曾经实测过每次收到客户端数据时都通过 TCP 连接从 redis 拉取客户端数据,结果是会严重影响性能。而且因为是单 TCP 连接 redis(设计成多连接又会继续增加复杂度),redis 请求需要类似 HTTP 那样按顺序处理,会导致无法并行处理客户端数据。
    所以 map 比 redis 性能好时,为什么还要使用各种类型的数据库呢?因为有别的需求,仅用 map 不能满足这些需求。不能不看需求就认为不能用 map ,而且即使用了 redis ,本地也适合用 map 再增加一层缓存。
    比如说上述案例,如果改为全都直接读 SQL 数据库,SQL 数据库没有通知客户端缓存失效的接口。如果管理进程和服务进程通过 RPC 通信来交换数据,那基本等于重新实现了 redis 的功能,又要写很多 RPC 通信的代码,管理进程崩掉也会影响服务进程正常工作,还不如直接使用 redis 。
    mengdodo
        53
    mengdodo  
       308 天前
    完全没问题,但是要做好各种崩掉的可能性
    daiv
        54
    daiv  
       308 天前
    @csfreshman 启动的时候, 需要几秒, 要不要 30-60s
    documentzhangx66
        55
    documentzhangx66  
       308 天前
    @djoiwhud

    1.你想通过一堆经验性的东西,来掩饰你之前“只要不出现雪崩”的这句话,毫无意义,还说明了你的业务不值钱。

    2.你说这就是你的“大量公司实际在工程中应用的方案”,但你又没说这些大量公司,到底是世界前 500 强,还是那种只有一两个人的皮包公司。500 强的公司数量的确没有皮包公司多。

    3.不要总觉得别人是小白,会不会是你的水平不够,看不出别人的水平呢?

    我前一条回复你的那句话:为什么要发明数据库。其实就已经点题了,你自己没去深究整个数据库发展史,不去深究你在意的游戏行业,到底是怎么处理这个问题的,以及现有的处理方案,究竟是一种无奈,还是真正的好方案。

    4.你回复我之前,但凡认真爬下楼,看看我在前面回复别人的话,也许能让你看懂我的意思,看明白一个系统究竟应该如何取舍,如何设计。从热血传奇、WOW 、EVE 的数据库设计,到 TB 的交易系统设计,难道就不能给你一丁点启发?
    documentzhangx66
        56
    documentzhangx66  
       308 天前
    @ysc3839

    一个系统,有很多评价指标。性能,不是唯一指标。这个问题,我在前面回复别人时已经说了。

    那些只看中性能的中间件,很多年前别人就用 C/CPP 玩烂了,我都不屑于去讨论这个问题。你看看楼上一堆人在讨论 Redis ,几个人提到 Oracle ?

    当你的系统,从正规数据库取数据,居然会成为性能瓶颈,那么,你有没有想过,可能是最初的需求,或者最初的系统架构方案,或者是硬件设备选择,出了问题?如果在系统设计时,居然要为了性能,放弃一套成熟系统的其他方面,这套系统是不是有问题?
    ysc3839
        57
    ysc3839  
       308 天前 via Android
    @documentzhangx66 所以你仍然是在不了解他人需求、现状的情况下,就急于否定?就举一个简单的例子,游戏客户端高频低延迟和服务端进行通信,服务端每收到一个包都通过 TCP 从 redis 或其他数据库请求客户端信息,难道不会成为性能瓶颈吗?再者,我只是在 redis 的基础上加上了进程内的缓存,就叫“放弃一套成熟系统的其他方面”?
    documentzhangx66
        58
    documentzhangx66  
       308 天前
    @ysc3839

    [服务端每收到一个包都通过 TCP 从 redis 或其他数据库请求客户端信息]

    无论是 CS Go ,SC 2 、或者王者荣耀,都不会有这种面向辞职式设计。

    我建议你先去看看成熟的游戏的网络引擎,到底是怎么通信的。
    djoiwhud
        59
    djoiwhud  
       308 天前 via Android
    @documentzhangx66

    说个你不爱听的话。我看明白了你压根没什么实际从业经验。再混三五年经验再来反驳我吧。

    我是混了十几年开发经验了。我 10 年前,花一两个月每天下班熬夜看 redis 源码的时候,你应该还没写过一行代码。

    一个很简单的东西,让你搞,企业没个三五百人的技术团队都不用考虑开工了。

    你压根没理解简单的事,简单的处理。还停留在小白学了点皮毛,急不可耐的找机会实践一下炫耀一下,就觉得世界应该那样运行。

    基本上所有的游戏业务都是重度依赖内存缓存。实时数据放 redis 的非常非常少。50 帧的同步频率,一毫秒的数据 io 都是不可容忍的。

    你真的太幼稚了。还有心思谈业务不值钱。这年头还死磕 battle 那点烂代码值不值钱?行业都什么样了?

    信不信你失业了照样一个月没一两次面试机会。
    documentzhangx66
        60
    documentzhangx66  
       307 天前
    @djoiwhud

    1.你在低端公司,别说混了几十年,就算混了几万年,也就那样了。

    我在前面让你去看看一流公司的产品,是怎么设计网络的,看来你是一个字都没看进去。

    #
    2.你说你熬夜看 redis 源码,这只能说明你不是计算机专业,或者上课根本没听讲,导致基础极差。

    基础扎实的人,看看 redis 这玩意的功能特性,就能大致猜中它的运作模式,以及优劣,还用得着去翻源码?

    #
    3.游戏业务依赖内存?

    你可知道游戏也分 RTS 和 WebGame ?那些渣渣 WebGame 用得着重度依赖内存?

    所以说,你在低端公司混了几十年,连游戏的分类都搞不清楚。

    #
    4.50 帧的同步频率,一毫秒的数据 io 都是不可容忍的。你这句话,更是印证了我前面说的,你连游戏的网络设计,毛都不懂。

    有空还是去看看人家一流游戏的网络,到底是怎么设计的。

    一毫秒都不能容忍,很多玩家吃鸡或 10 人团战时,偶尔高达一两百 ms 的延迟,岂不是得封号处理?

    #
    5.最后提醒一下,没基础,在行业里混了很多年,这种人不是高手,而是老混子。
    Masoud2023
        61
    Masoud2023  
       307 天前
    这个确实得具体场景具体分析,如果不是那种延迟敏感场景,我觉得交给 redis 应该也没什么,看具体的取舍了。
    djoiwhud
        62
    djoiwhud  
       307 天前
    @documentzhangx66

    呵呵。你开心就好。我错没错,我心理有数。你错没错,你根本没认知。


    游戏分类是你这样分的?还分 RTS-webgame ,真是笑话。别人说的依赖内存,你搞半天以为是游戏客户端依赖内存。学生指点江山就这坏处。还客户端上百毫秒延迟?

    啥叫偏执狂,啥叫自以为是。

    包括 ysc3839 在内,说的问题都是 server 端,全部用户的实时战斗数据,状态数据,放在内存中。因为每个客户端每秒钟都有几十个请求,需要高频查询、修改状态数据,需要同步全局数据给大量用户。服务器即使是用 redis ,例如查一个用户的数据网络 IO 哪怕仅仅 1ms ,也是成本很高的。

    你看看你自己再谈什么?

    一下就暴露了毫无工程经验的菜鸡本质。
    morty0
        63
    morty0  
       307 天前
    map 不能缩容, 有内存泄露的风险
    smirkcat
        64
    smirkcat  
       307 天前
    建议了解下内存映射 kv 数据库,瞬间解决你的问题
    ysc3839
        65
    ysc3839  
       307 天前 via Android
    @documentzhangx66 我开发的根本不是游戏服务器,只是举个例子,你又急于否定了。
    而且这个问题只需要加多个进程内 map 进行缓存就能解决,举这个例子就是为了反驳你说的“觉得语言内置 map 性能比 Redis 好”,因为性能真的比只用 redis 好,redis 和 map 不是互斥关系,是互补关系。
    cheng6563
        66
    cheng6563  
       307 天前
    PS:redis 可以用 unix socket 连接。
    twing37
        67
    twing37  
       307 天前
    demo 且只读.完全没问题. 不放心就 zero gc 的 gocache,Ristretto 这些~

    我是支持层主 @djoiwhud 的那句:实时数据放 Redis 的非常非常少。某些情况下多余的 1ms io 的确很难容忍.
    documentzhangx66
        68
    documentzhangx66  
       307 天前
    @djoiwhud

    1.游戏怎么分类,有很多种角度。比如从游戏内容来说,完全可以参考 Steam 的分类。

    但如果从网络设计上进行分类,RTS 与 Web Game 的确属于不同的类别,并且 Web Game 其实还可以继续细分。

    你如果觉得,我这种分类方式不正确,你完全可以提出自己的分类看法。

    但如果你只是想来否定我的分类方法,却不提出自己的分类方法,那我觉得你这种行为,只是为了杠而杠,这类人我见多了。

    2.我不认同 ysc3839 的见解。而且,有没有一种可能,菜鸟与菜鸟,才会有认同感?

    3.我在前面说了,游戏的确很依赖内存。但你看看现在其他行业,工控、人工智障、医疗、数据存储,哪个不依赖内存?现在就连渣渣办公,都希望多加内存条,来提高 Office 、IM 软件的运行速度。你以为只有你游戏行业依赖内存?

    4.你说我看看我自己在谈什么?

    我在给你上课。

    你觉得我哪里说的有问题,你倒是指出来啊。

    你又指不出来,你只会否定,你这行为,和那些玻璃心的菜鸡,有啥区别?
    documentzhangx66
        69
    documentzhangx66  
       307 天前
    @ysc3839

    1.你用了一个 [急于否定] 的词。但在我看来,这其实是很正常的技术交流而已。

    所谓技术交流,就是你提出一个观点,我同意,就给你点赞;我不同意,我就提出反对,并且解释我为什么反对。

    如果你觉得,这种行为,叫 [急于否定] ,那么请你仔细看看你对我的回复,是不是也是 [急于否定] ?

    2.你在前面,提出了一个完全是外行的游戏网络设计,先不说让你去看看主流网络游戏是怎么设计的,就算是正常的计算机本科,但凡听课了,也不会做你说的那种让人血压拉满的设计吧?

    正确的设计思路,应该是,根据游戏业务,同时考虑网络原理,来进行联合设计。

    比如,当一个或多个数据包,达到触发一个业务函数的门槛时,Game Server 才会向 Cache Server 拉取数据处理请求。
    但并不代表一定是一个数据包就要处理一次。有很多优化方法的。比如去重、比如合并、比如省略非关键帧,比如强行设置对外调用频率,等等。

    而且客户端行为,并不是说服务端少处理一个包,或多了 1ms 的延迟,客户端就卡了。我在前面就说了,人家吃鸡、王者、甚至 SC2 ,有时候高达上百延迟,人家也有完善的处理方法。你不去学习,拍脑袋就觉得这样不好,那网络游戏还要不要搞?干脆以后全改成局域网游戏?

    3.我觉得我得重申一下,我并不是反对依赖内存,或者反对依赖内存对象。而是一个正常的设计,不能全靠内存对象。你知道当年热血传奇,为什么一到攻城就卡成 PPT 嘛 ? 你不去学习整个游戏 Server 的网络设计发展史,自然不了解这些问题。
    csfreshman
        70
    csfreshman  
       301 天前
    @daiv 差不多,多线程去读加载数据,这个时间无所谓,等加载完再去注册 consul vns 等对外提供服务。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1001 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 19:00 · PVG 03:00 · LAX 12:00 · JFK 15:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.