首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  Redis

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

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

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

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

    ps,多 db 没有性能提升(几乎没有?)
        6
    judeng   200 天前
    redis 的 db 没啥用,又没数据隔离,不如放一个 db 中
        7
    ilyh   200 天前   ♥ 1
    方法 2 没有什么问题啊, 我一直这么用, redigo 的连接池实现也是这样子
        8
    ilyh   200 天前   ♥ 1
    多 db 确实没有性能提升, 但管理起来还是方便一些
        9
    wuchujie   200 天前   ♥ 1
    没必要分 db。 项目上的 redis 一般可以分 2 个 db
    主要业务用 1 个。。
    另外一个可以存一些 log 或者后台平时要监测的数据。。
    业务环境主要用 1 个就可以
        10
    imherer   200 天前
    @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 才对呀?
        11
    polebug   200 天前 via Android   ♥ 1
    用 key 前缀划分就会
        12
    crohn   200 天前   ♥ 1
    不需要分 db,这和 MySQL 的分库不是一码事
        13
    katsusan   200 天前
    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. */
    }
    ```
        14
    ilyh   200 天前
    @imherer MaxActive 得看你的应用负载情况.
    既然 MaxIdle=1 那就有一个连接不会被回收啊, connected_clients=2 没毛病, MaxIdle=0 才会被回收
        15
    zarte   200 天前
    我分 db 是用来做全部清除用的
        16
    zarte   200 天前
    怀疑你的代码有并发问题导致 dbid 错了
        17
    pastgift   158 天前
    应该是并发问题导致的
    我也同意楼上说的不需要分 db,加业务前缀即可

    如果一定要分 db,其实没必要每次 select,还不如按照不同业务数据建不同的 redisClient
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2342 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 25ms · UTC 14:52 · PVG 22:52 · LAX 06:52 · JFK 09:52
    ♥ Do have faith in what you're doing.