Как повысить производительность Redis при 100% загрузке процессора? Шардинг? Самый быстрый клиент .Net?

Из-за значительного увеличения нагрузки на наш веб-сайт Redis теперь борется с пиковой нагрузкой, поскольку экземпляр сервера Redis достигает 100% загрузки ЦП (на одном из восьми ядер), что приводит к тайм-аутам.

Мы обновили наше клиентское программное обеспечение до ServiceStack V3 (из BookSleeve 1.1.0.4) и обновили сервер Redis до 2.8.11 (из 2.4.x). Я выбрал ServiceStack из-за существования Harbour.RedisSessionStateStore, в котором используется ServiceStack.Redis. Раньше мы использовали AngiesList.Redis вместе с BookSleeve, но и с ним мы испытали 100 %.

У нас есть восемь серверов Redis, настроенных как главное/подчиненное дерево. Один единственный сервер для состояния сеанса. Остальные предназначены для кеша данных. Один ведущий с двумя ведущими/ведомыми, подключенными к двум ведомым устройствам каждый.

Серверы удерживают около 600 клиентских подключений на пике, когда они начинают забиваться при 100% загрузке процессора.

Что мы можем сделать, чтобы повысить производительность?

Клиент Sharding и/или StackExchange Redis (насколько мне известно, клиент состояния сеанса не доступен...).

Или это может быть что-то другое? Сеансовый сервер также работает на 100% и не подключен ни к каким другим серверам (пропускная способность данных и сети низкая).


Обновление 1: анализ ИНФОРМАЦИИ redis-cli

Вот вывод команды INFO после одной ночи работы Redis 2.8.

# Server
redis_version:2.8.11
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7a57b118eb75b37f
redis_mode:standalone
os:Linux 2.6.32-431.11.2.el6.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.4.7
process_id:5843
run_id:d5bb838857d61a9673e36e5bf608fad5a588ac5c
tcp_port:6379
uptime_in_seconds:152778
uptime_in_days:1
hz:10
lru_clock:10765770
config_file:/etc/redis/6379.conf

# Clients
connected_clients:299
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:80266784
used_memory_human:76.55M
used_memory_rss:80719872
used_memory_peak:1079667208
used_memory_peak_human:1.01G
used_memory_lua:33792
mem_fragmentation_ratio:1.01
mem_allocator:jemalloc-3.2.0

# Persistence
loading:0
rdb_changes_since_last_save:70245
rdb_bgsave_in_progress:0
rdb_last_save_time:1403274022
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:3375
total_commands_processed:30975281
instantaneous_ops_per_sec:163
rejected_connections:0
sync_full:10
sync_partial_ok:0
sync_partial_err:5
expired_keys:8059370
evicted_keys:0
keyspace_hits:97513
keyspace_misses:46044
pubsub_channels:2
pubsub_patterns:0
latest_fork_usec:22040

# Replication
role:master
connected_slaves:2
slave0:ip=xxx.xxx.xxx.xxx,port=6379,state=online,offset=272643782764,lag=1
slave1:ip=xxx.xxx.xxx.xxx,port=6379,state=online,offset=272643784216,lag=1
master_repl_offset:272643811961
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:272642763386
repl_backlog_histlen:1048576

# CPU
used_cpu_sys:20774.19
used_cpu_user:2458.50
used_cpu_sys_children:304.17
used_cpu_user_children:1446.23

# Keyspace
db0:keys=77863,expires=77863,avg_ttl=3181732
db6:keys=11855,expires=11855,avg_ttl=3126767

Обновление 2: twemproxy (шардинг)

Я обнаружил интересный компонент под названием twemproxy. Этот компонент, насколько я понимаю, может шардить по нескольким экземплярам Redis.

Поможет ли это разгрузить процессор?

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


person baskabas    schedule 19.06.2014    source источник
comment
Можете ли вы уточнить: у Redis высокий процессор или ваш веб-уровень? Это важно уяснить. Что такое оперировать? (Redis показывает мгновенный счетчик операций через информацию)   -  person Marc Gravell    schedule 20.06.2014
comment
@Marc: я уточнил пост. Я посмотрю на opcount. Команда info работает очень медленно во время этих загрузок.   -  person baskabas    schedule 20.06.2014


Ответы (3)


Мое первое простое предложение, если вы еще этого не сделали, было бы, по крайней мере, отключить все резервные копии RDB или AOF на вашем Мастере. Конечно, тогда ваши подчиненные могут отставать, если они все еще сохраняют на диск. См. это, чтобы получить представление о стоимости дампов RDB.

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

Кроме того, эта запись SO содержит хороший ответ о профилирование Redis

Дополнительная информация о вашем варианте использования и структуре данных будет полезна при принятии решения о том, есть ли простое изменение, которое вы могли бы внести в то, как вы на самом деле используете Redis, что дало бы вам улучшение.

Изменить. В ответ на ваш последний комментарий полезно отметить, что каждый раз, когда подчиненное устройство теряет соединение и снова подключается, оно повторно синхронизируется с ведущим устройством. В предыдущих версиях Redis это всегда была полная повторная синхронизация, поэтому это было довольно дорого. По-видимому, в версии 2.8 ведомое устройство теперь может запрашивать частичную повторную синхронизацию только тех данных, которые были пропущены с момента отключения. Я не очень разбираюсь в деталях, но если ваш мастер или любой из ваших подчиненных не на 2.8. * и у вас шаткое соединение, это может серьезно повредить производительности вашего процессора, постоянно заставляя ваш мастер повторно синхронизироваться. рабы. Подробнее здесь

person wallacer    schedule 19.06.2014
comment
Я готов попробовать это. Может ли кто-нибудь подтвердить, что это не вызывает никаких других проблем. - person baskabas; 20.06.2014
comment
Я также нашел настройку под названием rdbcompression = true. Может ли отключение этого сохранить ЦП? Или файл большего размера станет следующим узким местом? Памяти у нас более чем достаточно. - person baskabas; 20.06.2014
comment
который не вводит другие проблемы? отключить резервное копирование RDB? Мы запускаем нашего мастера и одного подчиненного устройства только для памяти. Нет RDB или AOF. Затем у нас есть еще один ведомый диск, который занимается созданием резервных копий дисков. Это не вызывает никаких других проблем ... Вы просто даете процессу redis-server меньше работы. - person wallacer; 20.06.2014
comment
да, отключение rdbcompression также должно снизить загрузку процессора. Но только если вы на самом деле сохраняете резервные копии rdb на своем мастере, чего я предлагаю вам не делать. Резервное копирование дисков — отличная работа для ведомой машины... - person wallacer; 20.06.2014
comment
Да, спасибо Уолласер. Я уже вчитался в тему. Мы отключили сохранение RDB, так как оно нам не нужно. AOF был отключен по умолчанию. - person baskabas; 20.06.2014
comment
классно. Не стесняйтесь голосовать, если это было полезно ... просто скажите;) - person wallacer; 20.06.2014
comment
Я пытался, но для этого нужна репутация 15+... Посмотрим, будет ли это иметь какое-то значение сегодня вечером, но спасибо! ;) - person baskabas; 20.06.2014
comment
Отключение моментальных снимков и AOF немного разгрузило кеш. Коллега упомянул что-то о лимитах буфера fd=259 name= age=3 idle=3 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=3190 oll=25 omem =298154600 events=rw cmd=psync планируется закрыть как можно скорее для преодоления ограничений выходного буфера. [5843] 22 Jun 08:23:29.808 # Связь с ведомым xx.xx.xx.xx:6379 потеряна. - person baskabas; 22.06.2014

Мы обнаружили проблему внутри нашего приложения. Передача обновленных данных в нашем кеше в локальный кеш памяти реализована через подписку на канал Redis.

Каждый раз, когда локальный кеш очищался, срок действия элементов истекал или элементы обновлялись, сообщения отправлялись на все (35) веб-серверов, которые, в свою очередь, начинали обновлять больше элементов и т. д. и т. д.

Отключение сообщений для обновленных ключей улучшило нашу ситуацию в 10 раз.

Пропускная способность сети упала с 1,2 Гбит/с до 200 Мбит/с, а загрузка ЦП составляет 40% при 150% нагрузке, которую мы имели до сих пор в момент экстремальных вычислений и обновлений.

person baskabas    schedule 24.06.2014
comment
Интересный ответ и интересная проблема. Чтобы уточнить, вы использовали Redis pub/sub для синхронизации кешей в 35 веб-боксах, это правильно? Был ли там какой-то конкретный шаблон, который вы использовали, например, с помощью команды ключей, как было предложено в одном из ответов? Также из интереса, какая спецификация процессора была у машины Redis? - person Philip P.; 23.09.2014
comment
Ничего особенного, просто отправьте сообщение, когда ключ обновится в нашем CacheManager, и удалите этот ключ из локального кэша памяти на другом конце. ЦП: ЦП Intel(R) Xeon(R) E5-2670 0 @ 2,60 ГГц. - person baskabas; 25.09.2014

Первое, что нужно сделать, это посмотреть на slowlog get 50 (или выбрать любое количество строк) — это показывает последние 50 команды, которые заняли нетривиальное количество времени. Возможно, что-то из того, что вы делаете, просто занимает слишком много времени. Я беспокоюсь, если вижу что-нибудь в slowlog. Обычно я вижу объекты каждые несколько дней. Если вы видите множество элементов постоянно, то: вам необходимо выяснить, что вы на самом деле делаете на сервере. Одна убийственная вещь, которую никогда нельзя делать, это keys, но есть и другие вещи.

Следующее, что нужно сделать, это: кэш. Запросы, которые обрабатываются до того, как попадут в серверную часть, бесплатны. Мы широко используем Redis, но это не значит, что мы также игнорируем локальную память.

person Marc Gravell    schedule 20.06.2014
comment
Slowlog показывает 71 запись (и больше) в нашем кэше сеансов и 128 записей и больше в кеше данных. На данный момент мы не испытываем большой нагрузки. Как долго записи остаются здесь? Это много? - person baskabas; 20.06.2014
comment
@baskabas, по крайней мере, не звучит так, будто он непрерывен - если только он просто не обрезан до этого числа. Являются ли какие-либо из моментов атакующими большими? Я беспокоюсь о чем-либо более 5 мс. Но следующее, на что нужно обратить внимание, это монитор (кратко), чтобы увидеть, что на самом деле делает сервер. - person Marc Gravell; 20.06.2014
comment
Не могли бы вы уточнить свое последнее замечание (в ответе)? Мы используем локальный кэш памяти на наших веб-серверах, чтобы уменьшить нагрузку на наш кеш. Поскольку мы запускаем 2 рабочих процессов, мы теперь также размещаем локальный экземпляр Redis на каждом веб-сервере. Что произойдет, если мы сделаем их рабами? - person baskabas; 20.06.2014
comment
большинство записей находятся между 10 мс-20 мс. Два выделяются, оба PSYNC? -1 80мс-105мс. Опять же, у нас только 750 одновременных пользователей прямо сейчас... вчера вечером мы достигли 10K+. Я контролировал довольно много раз, и я просто вижу много ключей (и их данных), проходящих мимо. Что бы вы искали? - person baskabas; 20.06.2014
comment
@baskabas psync — это репликация, но это не звучит ужасно. Монитор был бы моим следующим шагом. - person Marc Gravell; 21.06.2014
comment
Сделаю в ночную смену. Увеличили емкость медленного журнала до 1024 (было 128), и он довольно быстро заполнился. - person baskabas; 22.06.2014