Redis Sentinel не подключается к мастеру: Ошибка: READONLY Вы не можете писать против ведомого только для чтения?

У меня есть этот redis replication с sentinel архитектором:

5 серверов: .1, .2, .3, .4 и .5

  • .1: приложение nodejs, Redis Master, Redis Sentinel
  • .2: приложение nodejs, подчиненное устройство Redis
  • .3: приложение nodejs, подчиненное устройство Redis
  • .4: редис-страж
  • .5: редис-страж

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

Итак, я предполагаю, что мое приложение не подключается к redis server через sentinel, а напрямую подключается к localhost.

Любая помощь приветствуется!

Обновление: журнал, когда я включаю 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, и все работает как шарм!!!


person Justin    schedule 15.03.2017    source источник


Ответы (2)


Ага, наконец нашел.

Это моя ошибка, когда старый код использует модуль Redis и пытается подключиться напрямую к локальному хосту.

Замените его на экземпляр ioredis, и он будет работать как шарм :)

person Justin    schedule 16.03.2017

Подключившись к «localhost», .2 и .3 общаются со своими локальными сохранениями, доступными только для чтения. Вы не «подключаетесь через часового». Вы подключаетесь к Sentinel, получаете основной IP-адрес, затем подключаетесь к этому IP-адресу и порту. По какой-то причине вы пытаетесь подключиться к локальному хосту, а не к IP-адресу, о котором сообщает дозорный. Что касается того, почему, я не могу сказать, поскольку информация не доступна в вашем вопросе.

Sentinel возвращает IP-адрес, а не «localhost», поэтому вы не используете возврат от sentinel, а вместо этого где-то закодированы для использования «localhost», что приведет к поведению, о котором вы сообщаете. Вам нужно найти это и исправить.

person The Real Bill    schedule 16.03.2017
comment
Спасибо за ваш комментарий, я тоже так думаю, однако в своем коде я пытался подключиться через sentinel-, как показано выше. И я не знаю, почему он пытается подключиться к локальному хосту??? - person Justin; 16.03.2017
comment
Обновление 2: еще одна вещь, я запускаю приложение на своем локальном компьютере в среде production, и все работает как шарм!!! - person Justin; 16.03.2017
comment
В моем случае проблема была из-за реплики локального хоста 6380. Когда ее заменили репликой 127.0.0.1 6380, проблема была решена. - person abbas; 16.07.2019