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

2019-05-22 13:24:28 +08:00
 imherer

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

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

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

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

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

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

那么问题来了:

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

12275 次点击
所在节点    Redis
17 条回复
huhu3312
2019-05-22 13:31:28 +08:00
完全没必要分 db,需要的话把 key 用业务划分即可(比如业务前缀),切换 db 需要消耗性能
gaius
2019-05-22 13:48:35 +08:00
db 只有单机才有,感觉没啥用..直接初始化 6 个也不是不可以
qwerthhusn
2019-05-22 13:55:14 +08:00
这个跟连接池有关系吧,对于 lurtence 的话,无论线程池多大,是只有一个 tcp 链接,多路复用的,你可以并发跑起来,用 netstat 看一下有几个连接
beshe
2019-05-22 14:08:10 +08:00
没必要分 db,反而增加了你的代码复杂度。如果只是为了区分不同的业务,直接在 key 里设置不同的前缀就可以了。另外分 db 也不太有利于你后面使用集群。
v2orz
2019-05-22 14:29:55 +08:00
同一楼,完全不需要分 db
而且后期你如果要使用 cluster,你使用多 db 反而需要改代码,因为 cluster 只有 db 0

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

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

如果一定要分 db,其实没必要每次 select,还不如按照不同业务数据建不同的 redisClient

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

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

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

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

© 2021 V2EX