V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
huahsiung
V2EX  ›  程序员

go 语言直接使用 map 和连接 Redis 后使用 Map 性能差别有多大

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

    go 语言直接使用 map 很方便

    map1 := make(map[string]int)
    key1 := map1["str1"]
    

    但是发现有些 go 项目源码偏向使用 Redis 等第三方的 map.

    import (
        github.com/go-redis/redis"
    )
     client := redis.NewClient(&redis.Options{
            Addr:     "localhost:6379", 
            Password: "",               
            DB:       0,                
        })
    client.Ping()
    client.HSet("myhash", "key1", "value1")
    value1, err := client.HGet("myhash", "")
    

    然后看到项目的 map 并不是并发使用的,数据量也不是特别大。(有些并没有持久需求的也在使用 redis )

    go map 和 redis map 都是内存使用的,而且速度也很快。但是很多需要查找 hash 关系表的项目,偏向使用如 redis map 等第三方表。

    我粗略测试了一下,没看出什么区别(可能我测试数据较小)。如果排除 go map 不能并发读写外与 Redis Map 使用性能差别有多大

    54 条回复    2024-01-17 14:51:19 +08:00
    zyxk
        1
    zyxk  
       347 天前
    我也想知道,等看结果
    nagisaushio
        2
    nagisaushio  
       347 天前 via Android
    楼主可以贴下测试代码吗?直觉上 redis 应该会慢很多,毕竟隔了个 tcp 传输
    yhtbiy
        3
    yhtbiy  
       347 天前   ❤️ 3
    这不是性能的问题吧,Redis 数据是可以持久的,你 go 内存里的重启了数据就都没了
    dobelee
        4
    dobelee  
       347 天前
    1. 你的例子过于简单,实际业务大多存储结构体,这就涉及编解码和序列化的 CPU 内存消耗。本地缓存无需。
    2. 你连接的是本地 redis ,连接耗时忽略,也不存在高峰期的网络波动。没有任何测试意义。
    doraemonki
        5
    doraemonki  
       347 天前 via Android
    应该是内置的快,没有持久化需求直接用内置的 map
    kneo
        6
    kneo  
       347 天前 via Android   ❤️ 1
    瞎猜一个一百倍。你可以自己测一下。
    Trim21
        7
    Trim21  
       347 天前 via Android
    内置大概的微秒级,Redis 毫秒级
    jinliming2
        8
    jinliming2  
       347 天前 via iPhone
    虽然不知道 go 原生 map 和用 Redis 的性能差异,即便是 Redis 更快,为什么只用 localhost:port 的 TCP 连接本地回环的方式来访问 Redis 呢?在 Linux 上使用 unix domain sockets 的方式不是会更快吗?根据 Redis 官方文档上的数据,unix sockets 的吞吐量能提高 50%。
    而不支持 unix sockets 的 windows 貌似用 Redis 本身就有性能瓶颈,感觉还不如直接用 go 原生 map 。
    bianhui
        9
    bianhui  
       346 天前
    得看,看 key 的数量,结构,数据类型,操作方法。稍微读一下两个源码就知道
    wdmx007
        10
    wdmx007  
       346 天前 via Android
    不是做二级缓存的话,在性能足够的情况下,用 redis 使应用无状态,有利于后续横向扩展
    sxfscool
        11
    sxfscool  
       346 天前
    场景不一样,没什么可比性
    sujin190
        12
    sujin190  
       346 天前 via Android   ❤️ 2
    微秒级和纳秒级,如果一个语言标准库 hash 表才有读 redis 的速度,那这语言太废了,没有 4 个数量级的差距说不定都是你用的有问题
    iseki
        13
    iseki  
       346 天前
    再注意下,数据序列化/反序列化
    fzdwx
        14
    fzdwx  
       346 天前
    你看的是什么项目?
    Nazz
        15
    Nazz  
       346 天前 via Android
    大概 100ns/op 和 1ms/op 的差异
    bthulu
        16
    bthulu  
       346 天前
    测试代码
    ```
    Dictionary<int, int> dict = new() { { 1, 1 } };
    Stopwatch stopwatch = Stopwatch.StartNew();
    int i = dict[1];
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedTicks);
    using ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
    IDatabase database = redis.GetDatabase();
    database.HashSet("key", 1, 1);
    stopwatch = Stopwatch.StartNew();
    RedisValue redisValue = database.HashGet("key", 1);
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedTicks);
    ```

    测试结果:
    ```
    746
    18209
    ```

    一句话: 内存 map 快 25 倍
    bthulu
        17
    bthulu  
       346 天前
    更新重复一万次测试结果
    ```
    Dictionary<int, int> dict = new() { { 1, 1 } };
    Stopwatch stopwatch = Stopwatch.StartNew();
    for (int i = 0; i < 10000; i++)
    {
    int j = dict[1];
    }
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedTicks);
    using ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
    IDatabase database = redis.GetDatabase();
    database.HashSet("key", 1, 1);
    stopwatch = Stopwatch.StartNew();
    for (int i = 0; i < 10000; i++)
    {
    RedisValue redisValue = database.HashGet("key", 1);
    }
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedTicks);
    ```
    输出
    ```
    1228
    9577919
    ```
    一句话: 内存 map 快 7800 倍
    acerphoenix
        18
    acerphoenix  
       346 天前
    一个内存读,可能还用 cpu 缓存,一个跨网络读
    alsas
        19
    alsas  
       346 天前
    肯定是本地快啊 没经过网络
    zzhaolei
        20
    zzhaolei  
       346 天前
    这个测试没意义啊,redis 能持久存储,map 不行,redis 也有一些回收和超时策略,这两个都不是一个东西,使用场景不一样
    Rehtt
        21
    Rehtt  
       346 天前 via Android   ❤️ 3
    这对比没意义,就像在问火车和远洋轮渡谁快
    wzw
        22
    wzw  
       346 天前
    小系统可以考虑直接用 goframe 的 gmap, 当缓存,

    系统启动的时候, 把所有数据读到 gmap 里面,

    速度超级快, 还省了序列化的时间
    8355
        23
    8355  
       346 天前
    举个例子
    你现在想去厕所
    去你家的厕所快
    还是去邻居家的厕所快
    wysnxzm
        24
    wysnxzm  
       346 天前   ❤️ 3
    我嫉妒你的才华
    nothingistrue
        25
    nothingistrue  
       346 天前
    如果性能一样的话,当然是 Redis 的更好,你可以把内存占用、自动超时等烦心事一股脑的扔给 Redis 去处理。

    但是性能是否一样,那还另说,不过这块我不擅长,不评论。

    再但是,性能是够用就好,不是越高越好。所以,只要性能差距对上层没那么敏感,还是以功能方便为首要选择依据。然而,借用 Redis 做 Map 是增加编码和运维复杂度的,所以一般场景的功能上也会偏向于使用内置 Map 。如果你发现一般场景都用 Redis Map 来取代内置 Map ,那很有可能是内置 Map 太烂了。
    RedisMasterNode
        26
    RedisMasterNode  
       346 天前
    有没有一种可能....用 Redis 的人寻求的是一个 "既可快速读写" ,"又可以多个服务(同个服务多个副本)" 访问的 KV 存储....

    我看楼主的意思,应该没有多个副本吧,就一个普通的单实例应用
    insert000
        27
    insert000  
       346 天前
    又没有可能是集群应用?
    realJamespond
        28
    realJamespond  
       346 天前
    tcp 传输完内存都操作几百次,你说哪个快?
    QlanQ
        29
    QlanQ  
       346 天前
    你说的这都不是一个事情吧,需求都不一样吧,内存只能单机用呀,会这样写,肯定是预留扩展吧
    jonsmith
        31
    jonsmith  
       346 天前
    redis 是数据库,跟本地操作怎么比,语言再拉跨也比网络快啊
    javaisthebest
        32
    javaisthebest  
       346 天前
    本地 Map 强多了为什么会出现 Redis?

    为什么 Redis 功能这么强大还是会有本地 Map ?

    先把这两个问题搞清楚吧。。 别一头雾水就提问
    cloverzrg2
        33
    cloverzrg2  
       346 天前
    外部的服务缓存,怎么能跟本地内存比速度。
    一个网络耗时,就比本地内存数据速度慢几百倍
    tairan2006
        34
    tairan2006  
       346 天前
    分布式缓存和内存缓存的应用场景完全不一样,对比无意义
    fgodt
        35
    fgodt  
       346 天前
    集群应用只能存 redis 自带的再快也不行
    shellcodecow
        36
    shellcodecow  
       346 天前
    一个是持久化 一个是不是 redis 要 io 耗时的啊 看应用场景分不同用法...

    如果是集群应用 那就要用到 redis
    seth19960929
        37
    seth19960929  
       346 天前
    你还是停留在单机呀, 当你上集群的时候, 你还用 map 吗
    而且机器之间怎么交换数据, 缓存控制这些
    sampeng
        38
    sampeng  
       346 天前
    哦。。那你这段数据同时被两个接口做 update ,请问阁下如何应对?
    wOuv7i4e7XxsSOR1
        39
    wOuv7i4e7XxsSOR1  
       346 天前
    莫民奇妙的问题
    wOuv7i4e7XxsSOR1
        40
    wOuv7i4e7XxsSOR1  
       346 天前
    莫名奇妙的问题
    allenby
        41
    allenby  
       346 天前 via Android
    肯定是直接内存快
    zoharSoul
        42
    zoharSoul  
       346 天前
    什么没头没尾的问题, 现在 go 程序员都这样?
    Daniel17
        43
    Daniel17  
       346 天前
    有没有可能是为了用 redis
    weijancc
        44
    weijancc  
       346 天前
    内置 map 肯定更快, 用 redis 是因为在分布式环境下可以共享, 以及可以持久化
    zdt3476
        45
    zdt3476  
       346 天前
    这都没必要测试吧,网络 IO 怎么能和内存比
    Seulgi
        46
    Seulgi  
       346 天前   ❤️ 5
    看了这个标题,眉头一皱,看了描述,眉头再皱,不知道具体想问什么问题。看了下面评论,眉头再一皱,还真有人在纠结讨论内置 map 和 redis 的性能。
    aababc
        47
    aababc  
       346 天前
    不知道这个帖子想表达和讨论的是什么内容,一脸懵逼
    darklost
        49
    darklost  
       346 天前
    多台机器跑横向扩展的时候就知道了
    huyan3280
        50
    huyan3280  
       346 天前
    这还用想,redis 有 IO 呀,当然是内存,
    xuanbg
        51
    xuanbg  
       346 天前
    肯定 Redis 要慢!但 Redis 可以持久化,也可以多机共享,这是你内存里面的 map 做不到的。所以,什么时候要用 Redis ,就很清楚了。
    flyingghost
        52
    flyingghost  
       345 天前
    "一段需要保存的文本"

    我发现一段文本用变量来存比用磁盘来存快上万倍哎!
    e7
        53
    e7  
       345 天前
    这属于常识性的问题,说明 op 还没入门啊
    z1829909
        54
    z1829909  
       345 天前
    本地存 map 的话, 要考虑不常用的数据回收掉, 不然内存一直涨. 还要考虑持久化, 多节点的话数据不一致. 折腾这么多不如直接 redis 了. redis 肯定是慢的, 因为需要通过网络获取数据, 慢多少取决于网络上消耗了多少
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   921 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 21:49 · PVG 05:49 · LAX 13:49 · JFK 16:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.