2014-02-01 2 views
3

У меня есть приложение, использующее redis. Я использовал ключевое имя user:<id> для хранения информации о пользователе. Затем локально я изменил код своего приложения, чтобы использовать для этого ключевое имя user:<id>:data.Перемещение схемы в Redis

Я боюсь, что если я нажму этот новый код на мой сервер, все будет разорвано. И причина этого в том, что, поскольку мой сервер redis на сервере уже будет иметь ключи, будут старые имена ключей.

Итак, единственный способ, по моему мнению, остановить мое приложение, изменить все старые имена ключей на новые &, а затем перезапустить его. У вас есть лучшая альтернатива? Спасибо за помощь :)

ответ

1

Нажатие нового кода в вашу производственную среду всегда является страшным делом (вот почему в этой профессии выживают только самые жесткие;)). Я настоятельно рекомендую, чтобы перед изменением производственного кода и базы данных убедитесь, что вы проверяете рабочий процесс и его результаты локально.

Практически любое обновление приложения требует его остановки, даже если это необходимо для замены соответствующих файлов. Это даже верно для любых изменений, которые связаны с базой данных именно по той причине, о которой вы говорили.

Даже если вы можете развернуть ваши изменения кода, не останавливая приложение как таковое (например, страницу PHP), вы все равно хотите, чтобы изменение базы данных выполнялось «атомарно», то есть без каких-либо запросов приложений, которые могли бы вмешаться и, возможно, были нарушены. Хотя некоторые базы данных могут быть отключены для обслуживания, даже тогда вы обычно останавливаете приложение, иначе ошибки будут генерироваться повсюду.

Если это действительно так, вы прекратите приложение (или поместите его в режим обслуживания) независимо от изменения базы данных, поэтому мы возьмем ваш вопрос, чтобы на самом деле означать: какой самый быстрый способ переименовать все/некоторые ключи в моей базе данных?

Чтобы ответить на этот вопрос, по аналогии с псевдо-код предложено выше, я предлагаю вам использовать скрипт Lua, такие как следующие и EVAL, как только вы остановите приложение:

for _,k in ipairs(redis.call('keys', 'user:*')) do 
    if k:sub(-5) ~= ':data' then 
     redis.call('rename', k, k .. ':data') 
    end 
end 

Несколько замечаний по этому поводу скрипт, который вы должны иметь в виду:

  1. Хотя команда КЛЮЧИ не является безопасным для использования в производстве, так как вы делаете обслуживание его можно использовать безопасно. Для всех других случаев использования, где вам нужно отсканировать ключи, SCAN Redis гораздо более целесообразен.

  2. Поскольку сценарии Lua являются «атомарными», вы можете теоретически запустить этот скрипт, не останавливая приложение, - пока скрипт работает (что зависит от размера вашего набора данных), запросы приложения будут заблокированы.Иными словами, этот подход решает проблему получения имен смешанных ключей (старый & новый). Это, однако, вероятно, не то, что вы хотели бы сделать в любом случае, потому что: а) ваше приложение все еще может быть ошибкой/таймаутом в течение этого времени, но главным образом потому, что b) он должен будет иметь возможность обрабатывать оба типа имен ключей (т.е. запуск со старыми ключами -> короткая/длинная пауза -> запуск с новыми клавишами) делает ваш код намного сложнее.

  3. Условие if не требуется, если вы собираетесь запускать сценарий только один раз и преуспеть.

  4. В зависимости от фактического содержимого вашей базы данных вы можете захотеть отфильтровать ключи, которые не следует переименовывать.

  5. Для обеспечения совместимости воздержитесь от hardcoding/вычислительно генерируя имена ключей - вместо этого они должны передаваться в качестве аргументов скрипту.

1

Вы можете запустить сценарий миграции на вашем клиентском языке redis, используя RENAME.

Если у вас нет другого контроля над общим количеством ключей, вы сначала выдаете KEYS user:*, чтобы перечислить все ключи, а затем подстроку для получения числового идентификатора, а затем переименование.

Вы можете выдать все это в transaction.

Так мало псевдокод и Redis команды:

MULTI 
KEYS user:* 
For each key { 
    id = <Get id from key> 
    RENAME user:id user:id:data 
} 
EXEC 

Поняли?

Смежные вопросы