我有 redis replication
的CC_1架构师:
5服务器:.1
,.2
,.3
,.4
和.5
-
.1
:Nodejs App,Redis Master,Redis Sentinel -
.2
:Nodejs App,Redis Slave -
.3
:Nodejs App,Redis Slave -
.4
:Redis Sentinel -
.5
:Redis Sentinel
前哨手柄故障转移如预期的。 redis-cli -h x.y.z.5 -p 26379 sentinel get-master-addr-by-name mymaster
始终返回.1
服务器。
我的代码连接到此复制(我使用ioredis):
let sentinels = [
{ host: process.env.REDIS_SENTINEL_1, port: process.env.REDIS_PORT },
{ host: process.env.REDIS_SENTINEL_2, port: process.env.REDIS_PORT },
{ host: process.env.REDIS_SENTINEL_3, port: process.env.REDIS_PORT }
]
store = new Redis({
name: 'mymaster',
sentinels: sentinels
})
store.on('ready', () => {
store.set('foo', new Date())
store.get('foo', function (err, result) {
console.log('redis: get foo: ', result)
});
});
然后, .1
nodejs应用程序运行正常,但是在.2
和.3
中,此日志发生错误:
events.js:161
throw er; // Unhandled 'error' event
^
Error: READONLY You can't write against a read only slave.
p/s:我的REDIS服务器在服务器IP和127.0.0.1
中均具有绑定。因为,如果没有127.0.0.1
,我遇到此错误:
Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
所以,我想,我的应用不会通过sentinel
1连接到redis server
,但是它直接与localhost
连接。
任何帮助都是appriciate!
更新:登录我打开DEBUG=ioredis:*
:
2|MyApp | Wed, 15 Mar 2017 12:58:42 GMT ioredis:redis status[x.y.z.5:26379]: connecting -> connect
2|MyApp | Wed, 15 Mar 2017 12:58:42 GMT ioredis:redis status[x.y.z.5:26379]: connect -> ready
2|MyApp | Wed, 15 Mar 2017 12:58:42 GMT ioredis:connection send 1 commands in offline queue
2|MyApp | Wed, 15 Mar 2017 12:58:42 GMT ioredis:redis write command[0] -> sentinel(get-master-addr-by-name,mymaster)
2|MyApp | events.js:161
2|MyApp | throw er; // Unhandled 'error' event
2|MyApp | ^
2|MyApp | Error: READONLY You can't write against a read only slave.
2|MyApp | at JavascriptReplyParser._parseResult (/home/demo/demo_api/source/node_modules/redis/lib/parsers/javascript.js:43:16)
2|MyApp | at JavascriptReplyParser.try_parsing (/home/demo/demo_api/source/node_modules/redis/lib/parsers/javascript.js:114:21)
2|MyApp | at JavascriptReplyParser.run (/home/demo/demo_api/source/node_modules/redis/lib/parsers/javascript.js:126:22)
2|MyApp | at JavascriptReplyParser.execute (/home/demo/demo_api/source/node_modules/redis/lib/parsers/javascript.js:107:10)
2|MyApp | at Socket.<anonymous> (/home/demo/demo_api/source/node_modules/redis/index.js:131:27)
2|MyApp | at emitOne (events.js:96:13)
2|MyApp | at Socket.emit (events.js:189:7)
2|MyApp | at readableAddChunk (_stream_readable.js:176:18)
2|MyApp | at Socket.Readable.push (_stream_readable.js:134:10)
2|MyApp | at TCP.onread (net.js:551:20)
2|MyApp | [nodemon] app crashed - waiting for file changes before starting...
2|MyApp | sentinel production
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis status[localhost:6379]: [empty] -> connecting
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis status[x.y.z.5:26379]: [empty] -> connecting
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis queue command[0] -> sentinel(get-master-addr-by-name,mymaster)
2|MyApp | sentinel production
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis status[localhost:6379]: [empty] -> connecting
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis status[x.y.z.5:26379]: [empty] -> connecting
2|MyApp | Wed, 15 Mar 2017 12:58:43 GMT ioredis:redis queue command[0] -> sentinel(get-master-addr-by-name,mymaster)
更新2:另一件事,我在production
环境中运行该应用程序,并且一切都像魅力一样工作!
如果发生上述错误,则表示当前的redis服务是只读的,并且没有写入权限。据估计,该服务被用作从数据库。
解决方案1
打开与Redis服务相对应的配置文件,并将属性从属阅读的值修改为否,以便可以写入。
解决方案2
或更快的方法是通过运行此命令
redis-cli -h 127.0.0.1 -p 6379 slaveof no one
命令阻止当前的Redis服务从其他Redis服务接收同步,同时升级到主数据库。
是的,终于找到了。
当旧代码使用redis模块并尝试直接连接到Localhost时,这是我的错误。
将其替换为ioredis实例,它像魅力一样工作:)
通过连接到" localhost",.2和.3正在与他们的本地阅读保存交谈。您不会"通过前哨连接"。您连接到Sentinel,获取主IP,然后连接到该IP和端口。由于某种原因,您试图连接到Localhost,而不是Sentinel报告的IP。关于为什么,我不能说,因为您的问题中没有信息。
Sentinel返回一个IP地址,而不是" Localhost",因此您不是使用Sentinel的返回,而是在某个地方编码以使用" Localhost",这将产生您报告的行为。您需要找到并修复它。