最近遇到一个无解的bug:项目里缓存用了redis,然后我用到了redis的几个库,比如index=0存用户信息,index=1存战报数据,index=2存关卡数据。 前段时间把代码部署到2台linux服务器上(做了负载的,两台服务器公共用一个redis服务器),跑了一段时间没发现问题。前几天更新了下代码,但是也没改过redis相关的东西,出现的问题是:A服务器一切正常,B服务器所有数据都跑到index=0的库里去了。两边的代码都是一样的,不知道什么原因。
我们的游戏也出现过这种问题,当时是因为忘了改服务器配置表
@jiurihuahuo 我两台服务器用的配置文件都是一样的。 但就是不知道什么原因导致的。=。=
你的redis数据操作有异常,在并发量低的情况下不会体现出来,举个栗子:假如有3个请求,分别是 1 :select 0 and set name cnode 2 :select 1 and set name cnode2 3 :select 0 and get name 对于应用层每次都是先select然后操作,但是对于redis server则不然,当高并发时到达server的请求可能是select 0 select 1 and set name cnode2 and set name cnode 接下来的事情,你懂得。数据乱跑,解决方案的话multi就好;
@haozxuan 不会吧,在redis-server还会出现这种情况? 不过你说的好像也挺有道理的,但是问题是,我现在把出问题那台服务器单独抽出来,就我一个人跑的时候依旧是全部在0里面。。。
@imhered 你指的index是redis的db编号吧?0号存用户一号存战报什么的
@fantasticsoul 对的,redis默认16个db编号吧,好像是。
保持连接不要关闭
@imhered 这个很正常,当并发量小(对redis的操作)的时候你传递到redis server的指令是有序的,但是当并发量大的时候,没有事物性保证select后一定是你想做的操作,你做个简单的demo就可以看出来,在一个服务进程中并行的操作,在redis server上开启monitor模式,就会发现,在没有事物保证的情况下,的确存在这样的现象;
@chloe 目前用了连接池,看样子得改改。
@haozxuan 嗯,首先非常感谢你的回答。 那用multi的话,就拿这个操作来说select 0 and set name cnode,client的操作是:multi>select 0>set name cnode>exec,这样对吧?如果用了multi的情况下,多个操作不会混乱吧,假如A连接上来先select 0,接着进行set操作,但是还没set的时候B连接上来又select 1,用了multi两个不会混乱吧?
mark
@imhered multi 标记事务开始,意味着 multi > …[ n个redis cmd ] > exec, 这一组命令是已近queued了的,你说A连接上来先select 0,这个命令一触发表示已近将所有redis命令提交到redis-server了,后面一连串的命令都会被原子性地执行结束,redis也是单线程的,既然是单线程,multi又是拿来保证一连串的cmd原子性地执行,那就不存在你说的【假如A连接上来先select 0,接着进行set操作,但是还没set的时候B连接上来又select 1】这种情况了…B连接就算连接上来也要等A连接里那一串执行完哦
@fantasticsoul 好的,明白了,多谢!