跳至內容 跳至搜尋

Redis 快取儲存

部署注意事項:應小心使用專用 Redis 快取,而非針對於一個持續的 Redis 伺服器(例如,一個用於 Active Job 佇列的伺服器)。Redis 無法順利處理混和的使用模式,而且它不會預設到期快取條目。

Redis 快取伺服器設定指南:redis.io/topics/lru-cache

  • 支援基礎 Redis、hiredis 及 Redis::Distributed

  • 使用 Redis::Distributed 支援類似 Memcached 的 Redis 分割。

  • 具備容錯能力。如果 Redis 伺服器不可用,將不會引發例外。Cache 擷取全都遺漏,而寫入則捨棄。

  • 本機快取。在區塊/中介軟體範圍內熱門的記憶體中主要快取。

  • 支援 read_multiwrite_multi 以使用 Redis mget/mset。對於分散式 mget 支援,請使用 Redis::Distributed 4.0.1+。

  • 支援 delete_matched 以使用 Redis KEYS 全域通配符。

方法
C
D
I
N
R
S

常數

DEFAULT_ERROR_HANDLER = -> (method:, returning:, exception:) do if logger logger.error { "RedisCacheStore: #{method} 失敗,已傳回 #{returning.inspect}: #{exception.class}: #{exception.message}" } end ActiveSupport.error_reporter&.report( exception, severity: :warning, source: "redis_cache_store.active_support", ) end
 
DEFAULT_REDIS_OPTIONS = { connect_timeout: 1, read_timeout: 1, write_timeout: 1, }
 
MAX_KEY_BYTESIZE = 1024
 

如果超過 1kB,將使用 Active Support 摘要來截斷金鑰。

屬性

[R] max_key_bytesize
[R] redis

類別公開方法

new(error_handler: DEFAULT_ERROR_HANDLER, **redis_options)

建立新的 Redis 快取儲存。

有四種方法可以提供快取所使用的 Redis 用戶端::redis 參數可以是 Redis 實體或傳回 Redis 實體的區塊,或者 :url 參數可以是字串或字串陣列,該陣列將用於建立 Redis 實體或 Redis::Distributed 實體。

Option  Class       Result
:redis  Proc    ->  options[:redis].call
:redis  Object  ->  options[:redis]
:url    String  ->  Redis.new(url: …)
:url    Array   ->  Redis::Distributed.new([{ url: … }, { url: … }, …])

預設不設定名稱空間。如果 Redis 快取伺服器與其他應用程式共用,請提供一個名稱空間:namespace: 'myapp-cache'

預設啟用了壓縮,並具有 1kB 的閾值,因此大於 1kB 的快取值會自動壓縮。傳遞 compress: false 以停用或傳遞 compress_threshold: 4.kilobytes 以變更閾值。

在快取條目上預設不設定到期日。預期 Redis 會設定為具有驅逐原則,而這樣的原則會在 Redis 達到最大記憶體時自動刪除最近最少或最常使用的金鑰。請參閱 redis.io/topics/lru-cache 來取得快取伺服器設定。

競爭狀態 TTL 預設不設定。這可以用於避免熱門快取條目到期時出現「暴風驟雨」快取寫入。請參閱 ActiveSupport::Cache::Store#fetch 以取得詳細資訊。

設定 skip_nil: true 將不會快取 nil 結果。

cache.fetch('foo') { nil }
cache.fetch('bar', skip_nil: true) { nil }
cache.exist?('foo') # => true
cache.exist?('bar') # => false
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 149
def initialize(error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
  universal_options = redis_options.extract!(*UNIVERSAL_OPTIONS)

  if pool_options = self.class.send(:retrieve_pool_options, redis_options)
    @redis = ::ConnectionPool.new(pool_options) { self.class.build_redis(**redis_options) }
  else
    @redis = self.class.build_redis(**redis_options)
  end

  @max_key_bytesize = MAX_KEY_BYTESIZE
  @error_handler = error_handler

  super(universal_options)
end

supports_cache_versioning?()

宣傳快取版本控管支援。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 63
def self.supports_cache_versioning?
  true
end

執行個體公開方法

清理(選項 = 空值)

Cache 儲存 API 實作。

移除過期的項目。由 Redis 最近最少/使用頻率最低過期原生處理,因此不支援手動清理。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 282
def cleanup(options = nil)
  super
end

清除(選項 = 空值)

清除所有 Redis 伺服器上的快取。如果快取具有命名空間,可以在共用伺服器上安全使用。

防呆:會引發錯誤。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 290
def clear(options = nil)
  failsafe :clear do
    if namespace = merged_options(options)[:namespace]
      delete_matched "*", namespace: namespace
    else
      redis.then { |c| c.flushdb }
    end
  end
end

遞減(名稱,數量 = 1,選項 = 空值)

使用 Redis decrby 原子操作器遞減快取的整數值。傳回更新後的數值。

如果設定關鍵字已取消設定,或快取已過期,其將設為 -amount

cache.decrement("foo") # => -1

若要設定特定數值,請呼叫 寫入,並傳遞 raw: true

cache.write("baz", 5, raw: true)
cache.decrement("baz") # => 4

遞減非數字運算值或未用 raw: true 寫入的運算值將會失敗,並傳回 nil

防呆:會引發錯誤。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 267
def decrement(name, amount = 1, options = nil)
  options = merged_options(options)
  key = normalize_key(name, options)

  instrument :decrement, key, amount: amount do
    failsafe :decrement do
      change_counter(key, -amount, options)
    end
  end
end

刪除配對(比對器,選項 = 空值)

Cache 儲存 API 實作。

支援 Redis KEY 全域模式

h?llo matches hello, hallo and hxllo
h*llo matches hllo and heeeello
h[ae]llo matches hello and hallo, but not hillo
h[^e]llo matches hallo, hbllo, ... but not hello
h[a-b]llo matches hallo and hbllo

如果您想要逐字配對特殊字元,請使用 \ 進行跳脫。

請參 مراجعه redis.io/commands/KEYS,以取得更多資訊。

防呆:會引發錯誤。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 201
def delete_matched(matcher, options = nil)
  unless String === matcher
    raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}"
  end
  pattern = namespace_key(matcher, options)

  instrument :delete_matched, pattern do
    redis.then do |c|
      cursor = "0"
      # Fetch keys in batches using SCAN to avoid blocking the Redis server.
      nodes = c.respond_to?(:nodes) ? c.nodes : [c]

      nodes.each do |node|
        begin
          cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
          node.del(*keys) unless keys.empty?
        end until cursor == "0"
      end
    end
  end
end

遞增(名稱,數量 = 1,選項 = 空值)

使用 Redis incrby 原子操作器遞增快取的整數值。傳回更新後的數值。

如果設定關鍵字已取消設定,或快取已過期,其將設為 amount

cache.increment("foo") # => 1
cache.increment("bar", 100) # => 100

若要設定特定數值,請呼叫 寫入,並傳遞 raw: true

cache.write("baz", 5, raw: true)
cache.increment("baz") # => 6

遞增非數字運算值或未用 raw: true 寫入的運算值將會失敗,並傳回 nil

防呆:會引發錯誤。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 240
def increment(name, amount = 1, options = nil)
  options = merged_options(options)
  key = normalize_key(name, options)

  instrument :increment, key, amount: amount do
    failsafe :increment do
      change_counter(key, amount, options)
    end
  end
end

檢查()

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 164
def inspect
  "#<#{self.class} options=#{options.inspect} redis=#{redis.inspect}>"
end

讀取多筆(*名稱)

Cache 儲存 API 實作。

一次讀取多個值。傳回要求的鍵值對雜湊 -> 已擷取的值。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 172
def read_multi(*names)
  return {} if names.empty?

  options = names.extract_options!
  options = merged_options(options)
  keys    = names.map { |name| normalize_key(name, options) }

  instrument_multi(:read_multi, keys, options) do |payload|
    read_multi_entries(names, **options).tap do |results|
      payload[:hits] = results.keys.map { |name| normalize_key(name, options) }
    end
  end
end

stats()

從 redis 伺服器中取得資訊。

# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 301
def stats
  redis.then { |c| c.info }
end