您將學習兩種資料存放和擷取技術。選擇應用程式中要使用的方法時,請基於您的資料存取模式選取一種可簡化架構的方法。

不過,請先確認您可以 Redis。

完成單元的時間:60 分鐘



步驟 4.1

(按一下以放大)

步驟 4.1
步驟 4.2

(按一下以放大)

步驟 4.2

在範例中,應於每次提到端點時使用組態端點的主機名稱。

步驟 4.3

(按一下以放大)

步驟 4.3

syntax: shell

$ python

如果命令掛起,請參閱下列範例的備註。 

syntax: python

syntax: python
>>> import redis
>>> client = redis.Redis.from_url('redis://endpoint:6379')
>>> client.ping()

True

注意:如果當機,即表示您已遭到安全群組設定封鎖。驗證您的 EC2 執行個體可存取分配到 ElastiCache 執行個體的安全群組。例如,假設您的 EC2 執行個體被分配到預設的安全群組。您現在可以修改 Amazon ElastiCache 執行個體的安全群組,並新增自訂的 TCP 規則,許可預設安全群組中來自任何執行個體的連接埠 6379 上的連線:

在來源中,您可以開始輸入安全群組的名稱,並且能夠按下安全群組 ID。如果需要進一步了解安全群組,您可以查看文件安全群組規則參考

步驟 4.5

(按一下以放大)

步驟 4.5

資料儲存器中,您會發現一些可在 EC2 執行個體中執行的 Python 程式碼。但是,您首先需要設定一環境變數:

syntax: shell

$ export REDIS_URL=redis://your_redis_endpoint:6379/
$ export DB_HOST=your_mysql_endpoint
$ export DB_USER=admin
$ export DB_PASS=your_admin_password
$ export DB_NAME=tutorial

請注意,mysql_endpoint、redis_endpoin t和 password 的值是您在之前步驟中儲存的值。


程式碼範例中實作了兩種方法,第一種方法的運作方式是快取 SQL 查詢結果的序列化表示。以下 Python 程式碼片段說明了該邏輯:

syntax: python

def fetch(sql):

  result = cache.get(sql)
  if result:
    return deserialize(result)
  else:
    result = db.query(sql)
    cache.setex(sql, ttl, serialize(result))
    return result

首先,使用 SQL 陳述式作為 Redis 中的金鑰,然後檢查快取,看看是否存在值。如果不存在值,則使用 SQL 陳述式查詢資料庫。資料庫查詢的結果會儲存在 Redis 中。ttl 變數必須設定為合理的值,具體視應用程式的性質而定。ttl 過期時,Redis 會移出金鑰並釋放相關記憶體。教學資料儲存器中提供了該程式碼,您可按原樣予以執行,但是,如果您想在某個時間點查看變數值,則可以隨時在各處新增 print 陳述式。

就策略而言,這種方法的缺點是,在資料庫中修改了資料之後,如果已快取之前的結果且 ttl 尚未過期,則變更不會自動反映給使用者。

有關如何使用擷取函數的範例:

syntax: python

print(fetch("SELECT * FROM planet"))

結果將會是:

syntax: python

[{'id': 10, 'name': 'Mercury'},
 {'id': 11, 'name': 'Venus'},
 {'id': 12, 'name': 'Earth'},
 {'id': 13, 'name': 'Mars'},
 {'id': 14, 'name': 'Jupiter'},
 {'id': 15, 'name': 'Saturn'},
 {'id': 16, 'name': 'Uranus'},
 {'id': 17, 'name': 'Neptune'}]

當然,這是一個最基本的範例,但是透過實作這種快取模式,您的應用程式可從中大獲裨益,在這種模式下,從快取獲得的結果與直接取自資料庫的結果之間沒有任何差異。


您要實作的第二個範例會將資料庫記錄映射到 Redis 雜湊:

syntax: python

def planet(id):

  key = "planet:" + str(id)
  result = cache.hgetall(key)

  if result:
      return result

  else:
      sql = "SELECT `id`, `name` FROM `planet` WHERE `id`=%s"
      result = db_record(sql, (id,))

      if result:
          cache.hmset(key, result)
          cache.expire(key, ttl)
      return result

Redis 中的 Keyspace 是固定的,但是有一個慣例,即會使用冒號分隔字串來模擬結構。在該範例中,記錄 ID 1 的金鑰將為 "planet:1"。儘管此程式碼片段足以展現常見模式,但可以實現更多抽象:一個模組可負責生成金鑰,另一個模組可負責建置 SQL 字串等。此外,在您使用的程式設計語言中,可能存在為此目的建置的工具。
該範例會從快取或資料庫中擷取記錄,因此同樣地,可能存在一個負責將物件保存至資料庫的函數。


在這兩個範例中,您使用了存留時間 (ttl),之後 Redis 會移出金鑰。儘管在大多數情況下這已足夠,但是您可能希望盡快從快取中移除過時資料。如果這是您的使用案例,請確認您已核取其他選項,例如直接寫入快取策略。本教學結尾部分提供了其他詳細資訊的連結。值得一提的是,您可能感到好奇:雖然範例使用了 EXPIRE 命令,Redis 也提供了 EXPIREAT,因此您可以指定移出金鑰的確切日期和時間。其參數採用絕對 Unix 時間戳記 (即自 1970 年 1 月 1 日起經過的秒數)。


當資料量超過設定的最大記憶體設定時,Redis 具有不同的回應方式,具體視選取的移出政策而定。預設情況下,ElastiCache for Redis 設定為從記憶體中移除帶有 ttl 設定的近來最少使用的金鑰。移出政策參數稱為 maxmemory-policy,而 ElastiCache 中的預設值為 volatile-lru。此使用案例的另一個有趣選項是 volatile-ttl 政策,該政策會指示 Redis 移除 ttl 最短的金鑰,進而回收記憶體。


一旦實作了該政策,請務必測試您的應用程式,以找到 ttl 的最佳值和最佳移出政策。使用空快取和完整快取檢查應用程式的效能。