Redis事务执行期间其他客户端未被阻塞是否正常?
问题
以下是测试用的Go代码:
func main() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) pipe := rdb.TxPipeline() for i := 0; i < 10000; i++ { pipe.Set(ctx, "a", "abc", time.Second) } fmt.Println("Start") pipe.Exec(ctx) fmt.Println("End") }
当控制台打印Start时(此时End尚未打印),在Redis客户端执行get a命令,发现该命令未被阻塞,返回结果如下:
127.0.0.1:6379> get a (nil) 127.0.0.1:6379>
原本以为事务内的命令还未执行完毕,get命令应该被阻塞,请问这种情况是否正常?
解答
这种情况完全正常,原因和Redis事务的执行机制直接相关:
- Redis事务的核心逻辑是命令先入队,再批量执行。使用
TxPipeline时,循环调用的pipe.Set只是把命令添加到Go客户端的本地命令队列中,并没有立即发送给Redis服务器执行。 - 控制台打印
Start后才调用pipe.Exec(ctx),这一步才会把队列里的10000个Set命令一次性发送给Redis执行。也就是说,打印Start的那一刻,Redis服务器还没收到任何Set命令,自然不存在正在执行的事务,其他客户端的get命令也就不会被阻塞。 - 至于
get a返回(nil),是因为此时所有Set命令都还停留在Go客户端的本地队列里,Redis服务器中根本不存在a这个键,所以返回空值。
另外补充:即使Redis正在执行事务中的批量命令,也不会阻塞其他客户端的读操作——Redis是单线程处理命令,事务的命令会按顺序执行,但执行速度极快,通常不会让其他客户端产生明显的阻塞感。而你遇到的场景里,事务甚至还没开始在Redis端执行,所以完全不会影响其他客户端的操作。
内容的提问来源于stack exchange,提问作者woxihuanxiayua
相关产品推荐
相关产品推荐

