【问题标题】:How to debug/fix random occurring Redis::TimeoutError?如何调试/修复随机发生的 Redis::TimeoutError?
【发布时间】:2013-09-06 20:58:51
【问题描述】:

我有一个正在运行的 Rails 应用程序,它经常使用 redis - 但是 - 我看到很多 Redis::TimeoutError 不时出现在这里和那里。在这种情况下没有模式。它发生在 Web 应用程序和后台作业(正在使用 sidekiq 处理)中 - 不经常但不时发生。

现在我不知道如何追查此问题的根本原因,因此不知道如何解决它。

以下是我设置的一些背景知识:

redis 实例在单独的物理服务器上运行,该服务器连接到我的 Web 服务器和私有本地 1Gbit 网络中的后台服务器。所有服务器都运行 ubuntu 12.04。 redis 版本是 2.6.10。我正在使用像这样的初始化程序从我的 rails 应用程序(3.2)连接:

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

这是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

在我的 redis 配置中,我有以下设置:

\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 

【问题讨论】:

  • 所以超时错误是分批出现还是偶尔出现。
  • 还有什么 redis-cli --latency 在运行一段时间时会产生主机的最大延迟?
  • @MichaelPapile 我认为它们可能是小批量发生的——但不确定也不是很清楚——如果是这样的话——这根本不像是在幕布点或任何事情上都失败了
  • 延迟调用显示:min: 0, max: 2, avg: 0.26 (2682 samples)
  • 你用独角兽吗?如果是这样,它可能与此有关:github.com/resque/resque/issues/1018 还有这个解释github.com/redis/redis-rb/issues/340 不确定这些是否对你有帮助

标签: ruby-on-rails ruby redis


【解决方案1】:

这可能来自许多问题:

  • 因为您使用 SAVE 命令(在您的 conf 中设置)生成大量 I/O 并敲击服务器,尤其是如果您在 Amazon 上使用 EBS 卷。
  • 因为你有一个 Redis 从属设备(和以前一样,在镜像之前做SAVE)。
  • 因为您使用 KEY *,这在很多索引上都非常慢。

【讨论】:

  • 谢谢,我删除了链接,因为该网站已被删除。
【解决方案2】:
  1. 在redis服务器上尝试“slowlog”命令,看看是否有一些“慢查询”。
  2. 发生“TimeoutError”时写一些日志,看看“慢日志”中是否有“error redis command”。
  3. 在客户端调整你的超时设置。

【讨论】:

    【解决方案3】:

    如果服务器正常运行,可能是客户端的问题。每个 redis 客户端实例,而不是服务器,也有一个超时设置,默认设置很短——几毫秒。因此,如果服务器在该时间内没有响应,则客户端将引发 Redis::TimeoutError。

    您可以尝试的第一件事是设置更长的超时值,看看情况是否会好转。

    redis_url = 'redis://user:password@host:port/'
    redis = Redis.connect(:url => redis_url, :timeout => 0.7)
    

    即使设置更长的超时时间,也不能保证不会发生超时,但这将是您系统设计的问题。

    【讨论】:

      【解决方案4】:

      您是使用自己的代码连接到 redis 还是让 sidekiq 处理它?我认为你真的应该设计你的连接代码以在连接丢失时重新连接。您可以挽救 Redis::BaseConnectionError 并重新连接。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多