imherer
V2EX  ›  Redis

请教大佬们几个关于 redis 的问题

  •  
  •   imherer · May 22, 2019 · 13177 views
    This topic created in 2580 days ago, the information mentioned may be changed or developed.

    用 redis 做缓存,总共有 16db,在实际应用为了方便管理把不同的业务放在了不同的 db 中(虽然 16 个没全部用到,但基本上也用了差不多一半左右的样子)

    最开始操作 redis 的代码是这样的

    比如我要 SET 一个 string 到 db=1 的库中,命令顺序就是:SELECT > SET

    这样做了之后发现一个问题:并发稍微高了一点就会导致 dbindex 错乱,就是我明明想 SET 到 db=1 的库里,可能跑了到 db=2 的或者其他的库里

    于是将所有的 redis 操作改为了用事物来代替,即:MULTI > SELECT > SET > EXEC

    这样做了之后就没有问题了

    那么问题来了:

    • 1.全部用事物和不用事物有没有什么弊端(比如性能上的损耗啥的)
    • 2.比如我现在已经把我的业务划分好了,总共要用到 6 个 db,是不是一开始直接初始化 6 个 client 分别对应 1-6 的 db 来操作会好一点,这样我就不需要用事物了。但是这样会不会又会带来别的什么问题呢?(或者极限情况直接初始化 16 个 client )
    • 3.有没有必要分 db 存储呢? redis 设置 16 的 db 的原因应该不仅仅是为了方便管理吧?应该还是有性能上的考虑啥的吧?

    最后:开发语言用的是 go,client 使用的是redigo

    17 replies    2019-07-03 09:12:57 +08:00
    huhu3312
        1
    huhu3312  
       May 22, 2019 via iPhone   ❤️ 1
    完全没必要分 db,需要的话把 key 用业务划分即可(比如业务前缀),切换 db 需要消耗性能
    gaius
        2
    gaius  
       May 22, 2019   ❤️ 1
    db 只有单机才有,感觉没啥用..直接初始化 6 个也不是不可以
    qwerthhusn
        3
    qwerthhusn  
       May 22, 2019 via iPhone   ❤️ 1
    这个跟连接池有关系吧,对于 lurtence 的话,无论线程池多大,是只有一个 tcp 链接,多路复用的,你可以并发跑起来,用 netstat 看一下有几个连接
    beshe
        4
    beshe  
       May 22, 2019   ❤️ 1
    没必要分 db,反而增加了你的代码复杂度。如果只是为了区分不同的业务,直接在 key 里设置不同的前缀就可以了。另外分 db 也不太有利于你后面使用集群。
    v2orz
        5
    v2orz  
       May 22, 2019   ❤️ 1
    同一楼,完全不需要分 db
    而且后期你如果要使用 cluster,你使用多 db 反而需要改代码,因为 cluster 只有 db 0

    个人目前的理解是事务会带来性能下降,毕竟执行的命令多了?实际应用中没有使用过事务,类似场景都用 lua 脚本搞定了

    ps,多 db 没有性能提升(几乎没有?)
    judeng
        6
    judeng  
       May 22, 2019
    redis 的 db 没啥用,又没数据隔离,不如放一个 db 中
    ilyh
        7
    ilyh  
       May 22, 2019   ❤️ 1
    方法 2 没有什么问题啊, 我一直这么用, redigo 的连接池实现也是这样子
    ilyh
        8
    ilyh  
       May 22, 2019   ❤️ 1
    多 db 确实没有性能提升, 但管理起来还是方便一些
    wuchujie
        9
    wuchujie  
       May 22, 2019   ❤️ 1
    没必要分 db。 项目上的 redis 一般可以分 2 个 db
    主要业务用 1 个。。
    另外一个可以存一些 log 或者后台平时要监测的数据。。
    业务环境主要用 1 个就可以
    imherer
        10
    imherer  
    OP
       May 22, 2019
    @ilyh 请教下 redigo 连接池里 MaxIdle、MaxActive、IdleTimeout 这三个值建议设置多少合适呢?

    还有一点 IdleTimeout 这个值我没太搞明白。 我测试了下 MaxActive=1,MaxIdle=1,IdleTimeout=2 * time.Second 这样的配置的时候。当我 pool.Get 一个连接,然后操作完 redis 最后再 close 掉这个 conn 之后,通过 info 命令查看 connected_clients=2 (其中有一个是我 terminal 的连接)。 按 IdleTimeout 的配置,应该是过 2s 之后这个 idle 的 conn 已经被回收了 connected_clients=1 才对呀?
    polebug
        11
    polebug  
       May 22, 2019 via Android   ❤️ 1
    用 key 前缀划分就会
    crohn
        12
    crohn  
       May 22, 2019   ❤️ 1
    不需要分 db,这和 MySQL 的分库不是一码事
    katsusan
        13
    katsusan  
       May 22, 2019
    redis 下的多 db 就是初始化时申请了默认 12 个 redisDb 指针数组,用 0 号数据库的时候就是 server.db[0].性能应该和楼上所说都差不多。

    ```c
    struct RedisServer {
    ...
    redisDb *db; //初始化:server.db = zmalloc(sizeof(redisDb)*server.dbnum),dbnum 默认是 12
    ...
    }; -> struct RedisServer server (全局变量 server)
    ```

    当客户端 select 某个数据库的时候 redis 会将自己维护的客户端状态表里对应的客户端 redisDb 指定成 select 的那个数据库,
    至于为啥高并发会错乱具体要看执行时 redigo 为什么没有将命令有序送达到 redis 侧。

    ```c
    typedef struct client {
    redisDb *db; /* Pointer to currently SELECTed DB. */
    }
    ```
    ilyh
        14
    ilyh  
       May 22, 2019
    @imherer MaxActive 得看你的应用负载情况.
    既然 MaxIdle=1 那就有一个连接不会被回收啊, connected_clients=2 没毛病, MaxIdle=0 才会被回收
    zarte
        15
    zarte  
       May 22, 2019
    我分 db 是用来做全部清除用的
    zarte
        16
    zarte  
       May 22, 2019
    怀疑你的代码有并发问题导致 dbid 错了
    pastgift
        17
    pastgift  
       Jul 3, 2019
    应该是并发问题导致的
    我也同意楼上说的不需要分 db,加业务前缀即可

    如果一定要分 db,其实没必要每次 select,还不如按照不同业务数据建不同的 redisClient
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1345 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 73ms · UTC 16:55 · PVG 00:55 · LAX 09:55 · JFK 12:55
    ♥ Do have faith in what you're doing.