您將學習兩種資料存放和擷取技術。選擇應用程式中要使用的方法時,請基於您的資料存取模式選取一種可簡化架構的方法。
不過,請先確認您可以 Redis。
完成單元的時間:60 分鐘
syntax: shell
$ python
如果命令掛起,請參閱下列範例的備註。
syntax: python
syntax: python >>> import redis >>> client = redis.Redis.from_url('redis://endpoint:6379') >>> client.ping() True
在資料儲存器中,您會發現一些可在 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 的最佳值和最佳移出政策。使用空快取和完整快取檢查應用程式的效能。