2013-09-03 6 views
5

Mam uruchomioną aplikację szyny, która używa bardzo dużo redis - jednak - od czasu do czasu pojawia się tu sporo, co się zdarza Redis::TimeoutError. W tych okolicznościach nie ma wzorca. Występuje zarówno w aplikacji internetowej, jak i w pracy w tle (która jest przetwarzana przy użyciu sidekiq) - nie często, ale od czasu do czasu.Jak debugować/naprawiać losowe wystąpienia Redis :: TimeoutError?

Teraz nie mam pojęcia, jak wyśledzić główną przyczynę tego, a tym samym nie mam pojęcia, jak to naprawić.

Tutaj jest trochę tła na mojej konfiguracji:

Redis instancja jest uruchomiona na oddzielnym serwerze fizycznym, który jest podłączony zarówno do mojego serwera WWW i serwerem tle w prywatnej sieci lokalnej 1Gbit. Wszystkie serwery działają pod kontrolą Ubuntu 12.04. Wersja redis to 2.6.10. Łączę się z moim app szyn (czyli 3,2) przy użyciu inicjatora tak:

require 'redis' 
require 'redis/objects' 
REDIS = Redis.new(:url => APP_CONFIG['REDIS_URL']) 
Redis.current = REDIS 

To jest wyjście redis-cli INFO:

# Server 
redis_version:2.6.10 
redis_git_sha1:00000000 
redis_git_dirty:0 
redis_mode:standalone 
os:Linux 3.2.0-38-generic x86_64 
arch_bits:64 
multiplexing_api:epoll 
gcc_version:4.6.3 
process_id:28475 
run_id:d89bbb1b81d3169c4228cf23c0988ae437d496a1 
tcp_port:6379 
uptime_in_seconds:14913365 
uptime_in_days:172 
lru_clock:1507056 

# Clients 
connected_clients:233 
client_longest_output_list:0 
client_biggest_input_buf:0 
blocked_clients:19 

# Memory 
used_memory:801637360 
used_memory_human:764.50M 
used_memory_rss:594706432 
used_memory_peak:4295394784 
used_memory_peak_human:4.00G 
used_memory_lua:31744 
mem_fragmentation_ratio:0.74 
mem_allocator:jemalloc-3.3.0 

# Persistence 
loading:0 
rdb_changes_since_last_save:23166 
rdb_bgsave_in_progress:0 
rdb_last_save_time:1378219310 
rdb_last_bgsave_status:ok 
rdb_last_bgsave_time_sec:4 
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 

# Stats 
total_connections_received:932395 
total_commands_processed:3088408103 
instantaneous_ops_per_sec:837 
rejected_connections:0 
expired_keys:31428 
evicted_keys:3007 
keyspace_hits:124093049 
keyspace_misses:53060192 
pubsub_channels:0 
pubsub_patterns:0 
latest_fork_usec:17651 

# Replication 
role:master 
connected_slaves:1 
slave0:192.168.0.2,6379,online 

# CPU 
used_cpu_sys:54000.21 
used_cpu_user:73692.52 
used_cpu_sys_children:36229.79 
used_cpu_user_children:420655.84 

# Keyspace 
db0:keys=1498962,expires=1310 

W moim Redis config Mam następujący zestaw:

\fidaemonize yes 
pidfile /var/run/redis/redis-server.pid 
timeout 0 
loglevel notice 
databases 1 
save 900 1 
save 300 10 
save 60 10000 
stop-writes-on-bgsave-error yes 
rdbcompression yes 
rdbchecksum yes 
dbfilename dump.rdb 
dir /var/lib/redis 
slave-serve-stale-data yes 
slave-read-only yes 
slave-priority 100 
maxclients 1000 
maxmemory 4GB 
maxmemory-policy volatile-lru 
appendonly no 
appendfsync everysec 
no-appendfsync-on-rewrite no 
auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb 
lua-time-limit 5000 
slowlog-log-slower-than 10000 
slowlog-max-len 128 
hash-max-ziplist-entries 512 
hash-max-ziplist-value 64 
list-max-ziplist-entries 512 
list-max-ziplist-value 64 
set-max-intset-entries 512 
zset-max-ziplist-entries 128 
zset-max-ziplist-value 64 
activerehashing yes 
client-output-buffer-limit normal 0 0 0 
client-output-buffer-limit slave 256mb 64mb 60 
client-output-buffer-limit pubsub 32mb 8mb 60 
+0

A więc błędy przekroczenia limitu czasu występują w partiach lub sporadycznie. –

+0

także, co daje redis-klatkowy wydajność jako maksymalne opóźnienie dla hosta, gdy działa przez jakiś czas? –

+0

@MichaelPapile Myślę, że mogą występować w małych partiach - ale nie jestem pewien i niezbyt wyraźnie - jeśli tak - wcale nie jest tak, jakby wszystko kończyło się niepowodzeniem w punktach kurtyny lub czymkolwiek. –

Odpowiedz

7

To może pochodzić z wielu kwestii.

  • ponieważ użyć komendy SAVE (jest to ustawienie w conf) generuje dużo I/O i wbijanie serwera, szczególnie jeśli używasz woluminów EBS na Amazon.
  • ponieważ masz urządzenie podrzędne Redis (tak samo jak poprzednio, robiąc SAVE przed lustrzanym odbiciem).
  • ponieważ używasz KEY *, który jest bardzo wolny w wielu indeksach.

Napisałem artykuł na ten temat, zobacz here.

1

Może to być problem po stronie klienta, jeśli serwer działa normalnie. Każda instancja klienta redis, a nie serwer, ma również ustawienie limitu czasu, a ustawienie domyślne jest bardzo krótkie - trwa kilka milisekund. Jeśli więc serwer nie zareaguje w tym czasie, klient zostanie zgłoszony przez Redis :: TimeoutError.

Pierwszą rzeczą, którą możesz spróbować, to ustawić dłuższą wartość limitu czasu i sprawdzić, czy sytuacja się poprawi.

redis_url = 'redis://user:[email protected]:port/' 
redis = Redis.connect(:url => redis_url, :timeout => 0.7) 

Nawet przy dłuższym ustawienie limitu czasu, nie ma gwarancji, że limit czasu nie stało, ale to byłoby problemem przy projektowaniu systemu.

0

Czy rozwijasz swój własny kod, aby połączyć się z Redis lub po prostu pozwolić, aby go poradził? Myślę, że powinieneś po prostu zaprojektować swój kod połączenia, aby ponownie połączyć się, jeśli połączenie zostało utracone. Możesz uratować Redis :: BaseConnectionError i ponownie połączyć się.

2
  1. Wypróbuj polecenie "slowlog" na serwerze redis, aby sprawdzić, czy jest jakieś "wolne zapytanie".
  2. Zapisz niektóre logi, gdy pojawi się "TimeoutError", aby zobaczyć, czy polecenie "błąd redis" w "powolnym logu".
  3. dostosować ustawianiem czasu po stronie klienta