【AWS ElastiCache(Memcached)】将RDS查询结果进行缓存

目标

・AWS ElastiCache(Memcached)(※)を利用してRDSへのクエリをキャッシングするシステムを構築すること。
・キャッシングの方式はキャッシュ戦略(説明後述)に沿って構築を行う。

请参阅以下文章,了解有关ElastiCache的基本和详细信息
AWS缓存利用ElastiCache。

首先

これまでの記事でEC2⇔RDS、及びEC2⇔ElastiCacheの接続を構築したので、
今度はElastiCacheを利用してRDSへのクエリをキャッシングさせるプログラムをほぼポートフォリオ的なノリで書いてみました。
言語はRubyを利用しました。
実務で経験したことのない実装ですので、何か変なとこあったらコメントください笑

キャッシュ戦略(※)とは

在使用ElastiCache进行缓存时,这是AWS推荐的最佳实践。有两种不同的方式可供选择,根据系统的用例选择合适的策略。在这种情况下,我们将选择使用延迟加载进行实现。

・延迟加载
在数据加载时,首先查询缓存,若未能从缓存中找到数据,则访问数据源获取必要的数据,并将其写入缓存中的一种方式。
⇒可以减少缓存的内存使用量,但缓存数据可能过时(因为只在缓存未命中时才进行缓存写入)。

・写入忽略
每次在进行数据写入时都会将数据写入缓存的方式
⇒虽然会增加缓存的内存使用量,但始终可以获取最新的缓存数据

更详细的信息请参考AWS文档。
缓存策略
https://docs.aws.amazon.com/zh_cn/AmazonElastiCache/latest/mem-ug/Strategies.html

只需要一种选择的情况下,将以下内容用中文进行本地化改述:

先决条件。

・EC2とRDS(MySQL)間の接続が確立されていること(※1)。
・EC2とElactiCache(Memcached)間の接続が確立されていること(※2)。

※1 以下記事で構築済み
【RDS】EC2とRDS(MySQL)間の接続を確立する

※2 下面的文章是已经构建好的
【AWS ElastiCache】已经构建好了AWS ElastiCache(Memcached),并可以从EC2进行连接。

系统环境 (xì

・EC2
操作系统(AMI):Amazon Linux 2 AMI(HVM),SSD卷类型
软件:使用Ruby编写的自制程序

・RDS
エンジン: MySQL

弹性缓存引擎:Memcached

完成流程

当缓存命中时的流程如下

ElastiCache1 (3).png

发生缺失现金情况时,请按照以下流程操作。

Copy of ElastiCache2 (2).png

作业的流程

項番タイトル1デプロイ2動作検証

步驟

1. 部署

①登录EC2的操作系统

安装Ruby执行环境


$ sudo yum install ruby

③您可以安装Memocache客户端的Ruby gem(Ruby库)(※)
※ 参考资料:
16.6.3.7 在Ruby中使用MySQL和Memcached的网站


$ gem install Ruby-MemCache

安装Mysql客户端gem(※)
在使用Mysql客户端gem时,需要安装所需的库
(以下是在使用EC2的Amazon Linux 2时的步骤。在其他发行版中可能需要不同的库。)

※一个作为参考的文章
在AWS Cloud9的EC2上安装mysql2的gem库。


$ sudo yum -y install ruby-devel

sudo yum groupinstall "Development Tools"

sudo yum install mysql-devel

安装Mysql客户端的gem库


gem install mysql2

使用Ruby脚本(※)将其部署到EC2上。
请根据需要更改、、、、的值。


ファイル名: rds_cache.rb
# **********************************************************************************

# 機能概要: AWS ElastiCache(Memcached)を利用して、RDSへのクエリ結果をキャッシングする
# 機能詳細: ElastiCacheにクエリを発行し、キャッシュが存在する場合にはそのバリューを返す。
#       キャッシュが存在しない場合、データソースであるRDS(MySQL)にアクセスし結果表示後、ElastiCacheにキャッシュ保存する。
# スクリプト用法: ruby <スクリプトパス> "<検索SQLクエリ>"

# **********************************************************************************

unless ARGV.size() == 1
    puts "The number of arguments is incorrect."
    exit
end

# パッケージ
require 'base64'
require 'memcache'
require 'mysql2'

# 変数
sql_query = ARGV[0]                                                     # 実行SQLクエリ
cache_host = "<Elasticache_endpoint>"                                   # Elasticacheエンドポイント
cache_port = 11211                                                      # Elasticacheポート番号
db_host = "<rds_endpoint>"                                              # RDSエンドポイント
db_user = "<db_login_user>"                                             # DBログインユーザ
db_password = "<db_login_password>"                                     # DBパスワード
db_name = "<db_name>"                                                   # データベース名

# SQLクエリ(空白除去、小文字変換)をBase64でエンコード(キャッシュのキーとして利用する)
encoded_query = Base64.encode64(sql_query.gsub(" ", "").downcase)

# MemCache、Mysql接続用インスタンス作成
memc_connect = MemCache::new "#{cache_host}:#{cache_port}"
db_connect = Mysql2::Client.new(host: db_host, username: db_user, password: db_password, database: db_name)

# Elacacheからキャッシュを取得
cache_outcome = memc_connect[encoded_query]

if !cache_outcome[0].nil?
    puts "Cache HIT!"
    puts "[Query results from cache]"
    puts cache_outcome[0]
else
    puts "Cache MISS"
    puts "[Query results from datasource]"

    # キャッシュミスした場合、データベースへSQLクエリ発行
    sql_outcome = db_connect.query(sql_query) 

    cache_val = ""
    for row in sql_outcome do
        puts "--------------------"
        cache_val = cache_val + "--------------------\n"
        for key, value in row do
            puts "#{key} => #{value}"

            cache_val = cache_val + "#{key} => #{value}\n"
        end
    end

    # Elasticacheにバリューをセット
    memc_connect[encoded_query] = cache_val
end

※实施策略如下:
· 作为参数执行 SQL 查询脚本。
· 通过去除空格和转换为小写后,使用 Base64 对指定的 SQL 查询进行编码,然后作为 Elasticache 的键进行缓存搜索和保存。
· 如果缓存命中,则输出结果并结束脚本。
· 如果缓存未命中,则访问 RDS(数据源),执行 SQL 查询并输出结果。最后将该结果保存到 Elasticache 中。

2. 行动验证

验证数据库数据


+----+-----------+
| id | Name      |
+----+-----------+
|  1 | Ryosuke   |
|  2 | Tomoharu  |
|  3 | ryosuke   |
|  4 | shunsuke  |
|  5 | sato      |
|  6 | sato      |
|  7 | ryOsuke   |
|  8 | Kawashima |
|  9 | tomoharu  |
| 10 | RYOSUKE   |
+----+-----------+
tempsnip.png

①首次执行查询(缓存未命中模式)
输出缓存未命中消息,从数据源(RDS)正确地显示查询结果,因此OK。


$ ruby rds_cache.rb "SELECT * FROM test_table WHERE name = 'Ryosuke';"
Cache MISS
[Query results from datasource]
--------------------
id => 1
Name => Ryosuke
--------------------
id => 3
Name => ryosuke
--------------------
id => 7
Name => ryOsuke
--------------------
id => 10
Name => RYOSUKE

通过执行查询再次(缓存命中模式1)。输出的信息显示缓存命中成功,因此从Elasticache返回了正确的查询结果,表示OK。


[ec2-user@ip-172-31-34-150 ~]$ ruby rds_cache.rb "SELECT * FROM test_table WHERE name = 'Ryosuke';"
Cache HIT!
[Query results from cache]
--------------------
id => 1
Name => Ryosuke
--------------------
id => 3
Name => ryosuke
--------------------
id => 7
Name => ryOsuke
--------------------
id => 10
Name => RYOSUKE

重新执行调整为小写且修改了空格的查询(缓存命中模式2)。


[ec2-user@ip-172-31-34-150 ~]$ ruby rds_cache.rb "select *            from test_table where name = 'Ryosuke';"
Cache HIT!
[Query results from cache]
--------------------
id => 1
Name => Ryosuke
--------------------
id => 3
Name => ryosuke
--------------------
id => 7
Name => ryOsuke
--------------------
id => 10
Name => RYOSUKE

个中感受。

本来,这个系统的目的是通过利用缓存来加快查询响应速度并降低数据库负载,但是由于数据量太少,性能方面的优势无法确认,感觉有点说不出来的感觉…笑。希望有时间的话,能稍微确认一下这方面的情况。

广告
将在 10 秒后关闭
bannerAds