全部產品
Search
文件中心

ApsaraDB RDS:快取資料持久化

更新時間:Nov 20, 2024

當您使用雲資料庫RDS MySQL並需要提升資料處理速率和降低訪問延遲時,阿里雲為您提供了快取資料持久化的高效方案,該解決方案通過整合雲資料庫 Tair(相容 Redis)與RDS、KVStore for Memcache與RDS協同工作,確保資料的高速訪問和持久化儲存,具備高吞吐、低延遲等優勢。

背景資訊

與RDS相比,雲資料庫緩衝產品有如下兩個特性:

  • 響應速度快,雲資料庫 Tair(相容 Redis)和KVStore for Memcache請求的時延通常在幾毫秒以內。

  • 緩衝區能夠提供比RDS更高的QPS(每秒處理請求數)。

操作步驟

RDS MySQL與雲資料庫 Tair(相容 Redis)搭配

前提條件

  • 已建立Elastic Compute Service、雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL。

    • 如果僅需要通過內網訪問,則建議將三者建立在同一VPC下。

    • 如果已建立相關雲端服務,但三者不在同一VPC下,則可以分別為雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL開通外網串連地址,通過外網訪問。

    說明
    • 本文樣本的Elastic Compute Service鏡像版本為:Alibaba Cloud Linux 3.2104 LTS 64位

    • 本文樣本使用的開發語言為Python,請提前在Elastic Compute Service中安裝Python 3pip 3pymysqlredis-py

      pymysqlredis-py安裝命令如下:

      sudo pip3 install pymysql
      sudo pip3 install redis
  • 白名單設定:

    • 如果使用內網,請將VPC網段加入到雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL的白名單中。更多資訊,請參見Tair設定白名單RDS MySQL設定IP白名單

    • 如果使用外網,請分別為雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL開通外網串連地址,並將ECS的公網IP加入到雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL的白名單中。更多資訊,請參見Tair申請公網串連地址RDS MySQL申請外網地址

  • 雲資料庫 Tair(相容 Redis)和雲資料庫RDS MySQL已建立資料庫帳號和密碼。更多資訊,請參見Tair建立與管理帳號RDS MySQL建立帳號

配置步驟

  1. 登入Elastic Compute Service,編寫Python指令碼(本文樣本命名為test.py),類比業務情境,當從雲資料庫 Tair(相容 Redis)緩衝中查詢不到結果時,從雲資料庫RDS MySQL中查詢。

    警告

    本樣本所展示的代碼僅用於示範配置方式,請勿在實際業務代碼中將userpassword以明文方式設定在代碼中,建議使用外部設定檔或環境變數等其他方式進行處理後,再在代碼中引用。

    import json
    import redis
    import pymysql
    
    # 定義MySQL串連參數
    mysql_host = '<RDS MySQL串連地址>'
    mysql_user = '<使用者名稱>'
    mysql_password = '<密碼>'
    mysql_port = 3306
    mysql_charset = 'utf8'
    
    # 定義Tair(相容 Redis)串連參數
    redis_host = '<Tair串連地址>'
    redis_port = 6379
    # Tair(相容 Redis)密碼格式(帳號:密碼),如果沒有密碼則為空白字串
    redis_password = '<Tair密碼>'
    redis_db = 0
    
    
    def create_database_and_tables():
        db = pymysql.connect(host=mysql_host,
                             user=mysql_user,
                             password=mysql_password,
                             port=mysql_port,
                             charset=mysql_charset)
        cursor = db.cursor()
    
        # 建立測試資料庫
        cursor.execute("CREATE DATABASE IF NOT EXISTS testdb;")
    
        # 選擇資料庫
        cursor.execute("USE testdb;")
    
        # 建立測試表
        cursor.execute("""
        CREATE TABLE IF NOT EXISTS student (
            s_id INT AUTO_INCREMENT PRIMARY KEY,
            s_name VARCHAR(255) NOT NULL
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        """)
    
        # 插入測試資料
        cursor.execute("""
        INSERT INTO student (s_name) VALUES
        ('Zhangsan'),
        ('Lisi'),
        ('Wangwu')
        ON DUPLICATE KEY UPDATE s_name = VALUES(s_name);
        """)
    
        db.commit()
        cursor.close()
        db.close()
    
    
    def fetch_from_mysql():
        db = pymysql.connect(host=mysql_host,
                             user=mysql_user,
                             password=mysql_password,
                             database="testdb",
                             port=mysql_port,
                             charset=mysql_charset)
        cursor = db.cursor()
        cursor.execute("SELECT * FROM student")
        rows = cursor.fetchall()
        cursor.close()
        db.close()
        return rows
    
    
    def cache_to_redis(redis_client, key, data):
        # 將資料編碼成JSON字串以儲存複雜資料類型
        json_data = json.dumps(data)
        # 儲存到Tair(相容 Redis),並設定有效期間為600秒(10分鐘)
        redis_client.setex(key, 600, json_data)
    
    
    def get_from_redis(redis_client, key):
        # 嘗試從Tair(相容 Redis)擷取資料
        json_data = redis_client.get(key)
        if json_data:
            # 如果有資料,進行JSON解碼
            data = json.loads(json_data)
            return data
        else:
            return None
    
    
    def main():
        # 建立Tair(相容 Redis)用戶端
        redis_client = redis.StrictRedis(
            host=redis_host,
            port=redis_port,
            password=redis_password,
            db=redis_db,
            decode_responses=True  # 自動解碼響應
        )
    
        # 建立MySQL測試表並插入測試資料
        create_database_and_tables()
    
        # 定義Tair(相容 Redis)中儲存學生資訊的鍵
        redis_key = 'students'
    
        # 嘗試從Tair(相容 Redis)擷取資料
        students = get_from_redis(redis_client, redis_key)
    
        if students:
            print("從Tair查詢到資料:")
            print(students)
        else:
            print("Tair中未查詢到資料,從RDS MySQL查詢到資料:")
            # 從RDS MySQL擷取資料
            students = fetch_from_mysql()
            if students:
                print(students)
                # 快取資料到Tair(相容 Redis)
                cache_to_redis(redis_client, redis_key, students)
    
    
    if __name__ == '__main__':
        main()
    
  2. 運行test.py

    python3 test.py
    • 首次運行,由於Tair緩衝中沒有資料,從RDS MySQL中讀取,返回結果樣本:

      Tair中未查詢到資料,從RDS MySQL查詢到資料:
      ((1, 'Zhangsan'), (2, 'Lisi'), (3, 'Wangwu'))
    • 再次運行時,由於第一次查詢後已將查詢資料緩衝至Tair中,因此第二次直接從Tair緩衝中讀取資料。返回結果樣本:

      從Tair查詢到資料:
      [[1, 'Zhangsan'], [2, 'Lisi'], [3, 'Wangwu']]

RDS MySQL與KVStore for Memcache搭配

前提條件

  • 已建立Elastic Compute Service、KVStore for Memcache和雲資料庫RDS MySQL,且確保三者在同一VPC下。

    說明
    • KVStore for Memcache暫不提供外網訪問,僅支援通過內網訪問,因此,請確保三者在同一VPC下。

    • 本文樣本的Elastic Compute Service鏡像版本為:Alibaba Cloud Linux 3.2104 LTS 64位

    • 本文樣本使用的開發語言為Python,請提前在Elastic Compute Service中安裝Python 3pip 3pymysqlpython-memcached

      pymysqlpython-memcached安裝命令如下:

      sudo pip3 install pymysql
      sudo pip3 install python-memcached
  • 已將VPC網段加入到KVStore for Memcache和雲資料庫RDS MySQL的白名單中。更多資訊,請參見RDS MySQL設定IP白名單Memcache設定IP白名單

  • 雲資料庫RDS MySQL已建立資料庫帳號和密碼。更多資訊,請參見建立帳號

  • KVStore for Memcache已開啟免密登入。更多資訊,請參見免密碼訪問

配置步驟

  1. 登入Elastic Compute Service,編寫Python指令碼(本文樣本命名為test.py),類比業務情境,當從KVStore for Memcache緩衝中查詢不到結果時,從雲資料庫RDS MySQL中查詢。

    警告

    本樣本所展示的代碼僅用於示範配置方式,請勿在實際業務代碼中將userpassword以明文方式設定在代碼中,建議使用外部設定檔或環境變數等其他方式進行處理後,再在代碼中引用。

    import json
    import pymysql
    import memcache
    
    # 定義MySQL串連參數
    mysql_host = '<RDS MySQL串連地址>'
    mysql_user = '<使用者名稱>'
    mysql_password = '<密碼>'
    mysql_port = 3306
    mysql_charset = 'utf8'
    
    # 定義Memcache串連參數
    memcache_host = '<Memcache串連地址>:<連接埠>'
    
    
    def create_database_and_tables():
        db = pymysql.connect(host=mysql_host,
                             user=mysql_user,
                             password=mysql_password,
                             port=mysql_port,
                             charset=mysql_charset)
        cursor = db.cursor()
    
        # 建立測試資料庫
        cursor.execute("CREATE DATABASE IF NOT EXISTS testdb;")
    
        # 選擇資料庫
        cursor.execute("USE testdb;")
    
        # 建立測試表
        cursor.execute("""
        CREATE TABLE IF NOT EXISTS student (
            s_id INT AUTO_INCREMENT PRIMARY KEY,
            s_name VARCHAR(255) NOT NULL
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        """)
    
        # 插入測試資料
        cursor.execute("""
        INSERT INTO student (s_name) VALUES
        ('Zhangsan'),
        ('Lisi'),
        ('Wangwu')
        ON DUPLICATE KEY UPDATE s_name = VALUES(s_name);
        """)
    
        db.commit()
        cursor.close()
        db.close()
    
    
    def fetch_from_mysql():
        db = pymysql.connect(host=mysql_host,
                             user=mysql_user,
                             password=mysql_password,
                             database="testdb",
                             port=mysql_port,
                             charset=mysql_charset)
        cursor = db.cursor()
        cursor.execute("SELECT * FROM student")
        rows = cursor.fetchall()
        cursor.close()
        db.close()
        return rows
    
    
    def cache_to_memcache(memcache_client, key, data):
        # 將資料編碼成JSON字串以儲存複雜資料類型
        json_data = json.dumps(data)
        # 儲存到Memcache,並設定有效期間為600秒(10分鐘)
        memcache_client.set(key, json_data, time=600)
    
    
    def get_from_memcache(memcache_client, key):
        # 嘗試從Memcache擷取資料
        json_data = memcache_client.get(key)
        if json_data:
            # 如果有資料,進行JSON解碼
            data = json.loads(json_data)
            return data
        else:
            return None
    
    
    def main():
        # 建立Memcache用戶端
        memcache_client = memcache.Client([memcache_host], debug=0)
    
        # 建立MySQL測試表並插入測試資料
        create_database_and_tables()
    
        # 定義Memcache中儲存學生資訊的鍵
        memcache_key = 'students'
    
        # 嘗試從Memcache擷取資料
        students = get_from_memcache(memcache_client, memcache_key)
    
        if students:
            print("從Memcache查詢到資料:")
            print(students)
        else:
            print("Memcache中未查詢到資料,從RDS MySQL查詢到資料:")
            # 從RDS MySQL擷取資料
            students = fetch_from_mysql()
            if students:
                print(students)
                # 快取資料到Memcache
                cache_to_memcache(memcache_client, memcache_key, students)
    
    
    if __name__ == '__main__':
        main()
    
  2. 運行test.py

    python3 test.py
    • 首次運行,由於Memcache緩衝中沒有資料,從RDS MySQL中讀取,返回結果樣本:

      Memcache中未查詢到資料,從RDS MySQL查詢到資料:
      ((1, 'Zhangsan'), (2, 'Lisi'), (3, 'Wangwu'))
    • 再次運行時,由於第一次查詢後已將查詢資料緩衝至Memcache中,因此第二次直接從Memcache緩衝中讀取資料。返回結果樣本:

      從Memcache查詢到資料:
      [[1, 'Zhangsan'], [2, 'Lisi'], [3, 'Wangwu']]

相關文檔