快速入门:将 Azure Cache for Redis 与 Rust 配合使用

本文将介绍如何使用 Rust 编程语言来与 Azure Cache for Redis 交互。 你还将了解常用的 Redis 数据结构:

在本示例中,你将使用 Redis 的 redis-rs 库。 此客户端公开高级别和低级别 API,你可查看这两种样式的实际应用。

跳到 GitHub 上的代码

如果要直接跳到代码,请参阅 GitHub 上的 Rust 快速入门

先决条件

创建用于 Redis 的 Azure 缓存实例

  1. 若要创建缓存,请登录到 Azure 门户并选择“创建资源” 。

    左侧导航窗格中突出显示了“创建资源”。

  2. 在“入门”页上的搜索框中键入“Azure Cache for Redis”。 然后选择创建

    Azure 市场的屏幕截图,其中的搜索框中包含“Azure Cache for Redis”,并用红色框突出显示了“创建”。

  3. 在“新建 Redis 缓存”页上配置缓存的设置。

    设置 选择值 说明
    订阅 单击下拉箭头并选择你的订阅。 要在其下创建此新的 Azure Cache for Redis 实例的订阅。
    资源组 单击下拉箭头并选择一个资源组,或者选择新建并输入新的资源组名称。 要在其中创建缓存和其他资源的资源组的名称。 将所有应用资源放入一个资源组可以轻松地统一管理或删除这些资源。
    DNS 名称 输入唯一名称。 缓存名称必须是包含 1 到 63 个字符的字符串,只能包含数字、字母或连字符。 该名称必须以数字或字母开头和结尾,且不能包含连续的连字符。 缓存实例的主机名<DNS name>.redis.cache.chinacloudapi.cn
    位置 单击下拉箭头并选择一个位置。 选择使用缓存的其他服务附近的区域
    缓存 SKU 打开下拉列表并选择一个 SKU 此 SKU 决定可用于缓存的大小、性能和功能参数。 有关详细信息,请参阅用于 Redis 的 Azure 缓存概述
    缓存大小 打开下拉列表并选择缓存的大小 有关详细信息,请参阅用于 Redis 的 Azure 缓存概述
  4. 选择网络选项卡,或选择网络按钮(位于页面底部) 。

  5. 网络选项卡中,选择你的连接方法。

  6. 选择“下一步: 高级”选项卡,或选择页面底部的“下一步: 高级”按钮,以查看“高级”选项卡。

    显示工作窗格中的“高级”选项卡和可供选择选项的屏幕截图。

    • 对于“基本”或“标准”缓存,请切换非 TLS 端口的选项。 还可以选择是否要启用“Microsoft Entra 身份验证”。
    • 对于“高级”缓存,请配置非 TLS 端口、群集、托管标识和数据持久性的设置。 还可以选择是否要启用“Microsoft Entra 身份验证”。
  7. 选择下一步: 标记选项卡,或选择页面底部的下一步: 标记按钮 。

  8. 或者,在标记选项卡中,如果希望对资源分类,请输入名称或值。

  9. 选择“查看 + 创建”。 随后你会转到“查看 + 创建”选项卡,Azure 将在此处验证配置。

  10. 显示绿色的“已通过验证”消息后,选择创建

创建缓存需要一段时间。 可以在 Azure Cache for Redis 的概述页上监视进度。 如果“状态”显示为“正在运行”,则表示该缓存可供使用。

从 Azure 门户检索主机名、端口和访问密钥

若要连接到你的 Azure Cache for Redis 服务器,缓存客户端需要该缓存的主机名、端口和密钥。 在某些客户端中,这些项的名称可能略有不同。 可以从 Azure 门户检索主机名、端口和访问密钥。

  • 若要获取访问密钥,请从“资源”菜单中选择“身份验证”。 然后,选择“访问密钥”选项卡

    显示 Azure Cache for Redis 访问密钥的屏幕截图。

  • 若要获取缓存的主机名和端口,请从“资源”菜单中选择“概述”。 主机名的格式为 <DNS 名称>.redis.cache.chinacloudapi.cn

    显示 Azure Cache for Redis 属性的屏幕截图。

查看代码(可选)

如果有意了解代码的工作原理,可以查看以下代码片段。 否则,可以直接跳到运行应用程序

connect 函数用于与 Azure Cache for Redis 建立连接。 它需要分别通过环境变量 REDIS_HOSTNAMEREDIS_PASSWORD 传入主机名和密码(访问密钥)。 连接 URL 的格式为 rediss://<username>:<password>@<hostname> - Azure Cache for Redis 仅接受以 TLS 1.2 作为所需的最低版本的安全连接。

redis::Client::open 进行调用会执行基本验证,而 get_connection() 会实际启动连接。 如果连接因任何原因失败,程序将停止。 例如,其中一个原因可能是密码不正确。

fn connect() -> redis::Connection {
    let redis_host_name =
        env::var("REDIS_HOSTNAME").expect("missing environment variable REDIS_HOSTNAME");
    let redis_password =
        env::var("REDIS_PASSWORD").expect("missing environment variable REDIS_PASSWORD");
    let redis_conn_url = format!("rediss://:{}@{}", redis_password, redis_host_name);

    redis::Client::open(redis_conn_url)
        .expect("invalid connection URL")
        .get_connection()
        .expect("failed to connect to redis")
}

basics 函数涵盖 SETGETINCR 命令。

低级别 API 用于 SETGET,以设置和检索名为 foo 的键的值。

INCRBY 命令是使用高级别 API 执行的,即 incr2 为增量递增键(名为 counter)的值,然后调用 get 来检索该值。

fn basics() {
    let mut conn = connect();
    let _: () = redis::cmd("SET")
        .arg("foo")
        .arg("bar")
        .query(&mut conn)
        .expect("failed to execute SET for 'foo'");

    let bar: String = redis::cmd("GET")
        .arg("foo")
        .query(&mut conn)
        .expect("failed to execute GET for 'foo'");
    println!("value for 'foo' = {}", bar);

    let _: () = conn
        .incr("counter", 2)
        .expect("failed to execute INCR for 'counter'");
    let val: i32 = conn
        .get("counter")
        .expect("failed to execute GET for 'counter'");
    println!("counter = {}", val);
}

以下代码片段演示 Redis HASH 数据结构的功能。 使用低级别 API 调用 HSET,以存储有关 Redis 驱动程序(客户端)的信息(nameversionrepo)。 例如,Rust 驱动程序(在此示例代码中使用的驱动程序!)的详细信息以 BTreeMap 的形式捕获,然后传递到低级别 API。 然后使用 HGETALL 进行检索。

还可使用高级别 API 通过接受元组数组的 hset_multiple 执行 HSET。 然后执行 hget 以提取单个属性的值(在本例中为 repo)。

fn hash() {
    let mut conn = connect();

    let mut driver: BTreeMap<String, String> = BTreeMap::new();
    let prefix = "redis-driver";
    driver.insert(String::from("name"), String::from("redis-rs"));
    driver.insert(String::from("version"), String::from("0.19.0"));
    driver.insert(
        String::from("repo"),
        String::from("https://github.com/mitsuhiko/redis-rs"),
    );

    let _: () = redis::cmd("HSET")
        .arg(format!("{}:{}", prefix, "rust"))
        .arg(driver)
        .query(&mut conn)
        .expect("failed to execute HSET");

    let info: BTreeMap<String, String> = redis::cmd("HGETALL")
        .arg(format!("{}:{}", prefix, "rust"))
        .query(&mut conn)
        .expect("failed to execute HGETALL");
    println!("info for rust redis driver: {:?}", info);

    let _: () = conn
        .hset_multiple(
            format!("{}:{}", prefix, "go"),
            &[
                ("name", "go-redis"),
                ("version", "8.4.6"),
                ("repo", "https://github.com/go-redis/redis"),
            ],
        )
        .expect("failed to execute HSET");

    let repo_name: String = conn
        .hget(format!("{}:{}", prefix, "go"), "repo")
        .expect("HGET failed");
    println!("go redis driver repo name: {:?}", repo_name);
}

在下面的函数中,可了解如何使用 LIST 数据结构。 通过执行 LPUSH(使用低级别 API)将条目添加到列表,并使用高级别 lpop 方法从列表中检索该条目。 然后使用 rpush 方法将几个条目添加到列表中,再使用低级别 lrange 方法提取这些条目。

fn list() {
    let mut conn = connect();
    let list_name = "items";

    let _: () = redis::cmd("LPUSH")
        .arg(list_name)
        .arg("item-1")
        .query(&mut conn)
        .expect("failed to execute LPUSH for 'items'");

    let item: String = conn
        .lpop(list_name)
        .expect("failed to execute LPOP for 'items'");
    println!("first item: {}", item);

    let _: () = conn.rpush(list_name, "item-2").expect("RPUSH failed");
    let _: () = conn.rpush(list_name, "item-3").expect("RPUSH failed");

    let len: isize = conn
        .llen(list_name)
        .expect("failed to execute LLEN for 'items'");
    println!("no. of items in list = {}", len);

    let items: Vec<String> = conn
        .lrange(list_name, 0, len - 1)
        .expect("failed to execute LRANGE for 'items'");

    println!("listing items in list");
    for item in items {
        println!("item: {}", item)
    }
}

可在此处查看一些 SET 操作。 使用 sadd(高级别 API)方法将几个条目添加到名为 usersSET。 然后执行 SISMEMBER(低级别 API)以检查 user1 是否存在。 最后使用 smembers 以向量 (Vec<String>) 形式提取所有集合条目并对其进行循环访问。

fn set() {
    let mut conn = connect();
    let set_name = "users";

    let _: () = conn
        .sadd(set_name, "user1")
        .expect("failed to execute SADD for 'users'");
    let _: () = conn
        .sadd(set_name, "user2")
        .expect("failed to execute SADD for 'users'");

    let ismember: bool = redis::cmd("SISMEMBER")
        .arg(set_name)
        .arg("user1")
        .query(&mut conn)
        .expect("failed to execute SISMEMBER for 'users'");
    println!("does user1 exist in the set? {}", ismember);

    let users: Vec<String> = conn.smembers(set_name).expect("failed to execute SMEMBERS");
    println!("listing users in set");

    for user in users {
        println!("user: {}", user)
    }
}

下面的 sorted_set 函数演示排序集数据结构。 使用低级别 API 调用 ZADD,为播放机 (player-1) 添加随机整数分数。 接下来使用 zadd 方法(高级别 API)添加更多播放机(player-2player-5)及其各自(随机生成)的分数。 排序集内的条目数是使用 ZCARD 确定的。 它被用作 ZRANGE 命令(使用低级别 API 调用)的限制,以按分数升序列出播放机。

fn sorted_set() {
    let mut conn = connect();
    let sorted_set = "leaderboard";

    let _: () = redis::cmd("ZADD")
        .arg(sorted_set)
        .arg(rand::thread_rng().gen_range(1..10))
        .arg("player-1")
        .query(&mut conn)
        .expect("failed to execute ZADD for 'leaderboard'");

    for num in 2..=5 {
        let _: () = conn
            .zadd(
                sorted_set,
                String::from("player-") + &num.to_string(),
                rand::thread_rng().gen_range(1..10),
            )
            .expect("failed to execute ZADD for 'leaderboard'");
    }

    let count: isize = conn
        .zcard(sorted_set)
        .expect("failed to execute ZCARD for 'leaderboard'");

    let leaderboard: Vec<(String, isize)> = conn
        .zrange_withscores(sorted_set, 0, count - 1)
        .expect("ZRANGE failed");

    println!("listing players and scores in ascending order");

    for item in leaderboard {
        println!("{} = {}", item.0, item.1)
    }
}

克隆示例应用程序

首先从 GitHub 克隆应用程序开始。

  1. 打开命令提示符,然后创建一个新的名为 git-samples 的文件夹。

    md "C:\git-samples"
    
  2. 打开 git 终端窗口(例如 git bash)。 使用 cd 转到新文件夹,你将在这里克隆示例应用。

    cd "C:\git-samples"
    
  3. 运行下列命令,克隆示例存储库。 此命令在计算机上创建示例应用程序的副本。

    git clone https://github.com/Azure-Samples/azure-redis-cache-rust-quickstart.git
    

运行应用程序

应用程序接受环境变量形式的连接和凭据。

  1. Azure 门户中为 Azure Cache for Redis 实例提取“主机名”和“访问密钥”(可通过访问密钥获得) 。

  2. 将它们设置为相应的环境变量:

    set REDIS_HOSTNAME=<Host name>:<port> (e.g. <name of cache>.redis.cache.chinacloudapi.cn:6380)
    set REDIS_PASSWORD=<Primary Access Key>
    
  3. 在“终端”窗口中,切换到正确的文件夹。 例如:

    cd "C:\git-samples\azure-redis-cache-rust-quickstart"
    
  4. 在终端中,运行以下命令以启动应用程序。

    cargo run
    

    将会看到以下输出:

    ******* Running SET, GET, INCR commands *******
    value for 'foo' = bar
    counter = 2
    ******* Running HASH commands *******
    info for rust redis driver: {"name": "redis-rs", "repo": "https://github.com/mitsuhiko/redis-rs", "version": "0.19.0"}
    go redis driver repo name: "https://github.com/go-redis/redis"
    ******* Running LIST commands *******
    first item: item-1
    no. of items in list = 2
    listing items in list
    item: item-2
    item: item-3
    ******* Running SET commands *******
    does user1 exist in the set? true
    listing users in set
    user: user2
    user: user1
    user: user3
    ******* Running SORTED SET commands *******
    listing players and scores
    player-2 = 2
    player-4 = 4
    player-1 = 7
    player-5 = 6
    player-3 = 8
    

    如果要运行特定函数,请在 main 函数中注释禁止其他函数:

    fn main() {
        basics();
        hash();
        list();
        set();
        sorted_set();
    }
    

清理资源

要继续使用在本文中创建的资源,请保留资源组。

否则,如果已完成资源,可以删除创建的 Azure 资源组以避免产生费用。

重要

删除资源组的操作不可逆。 删除资源组时,包含在其中的所有资源会被永久删除。 请确保不会意外删除错误的资源组或资源。 如果在现有资源组(其中包含要保留的资源)内创建了此资源,可以逐个删除这些资源,而不是删除资源组。

删除资源组的步骤

  1. 登录到 Azure 门户,然后选择“资源组”。

  2. 选择要删除的资源组。

    如果有多个资源组,请使用“筛选任何字段...”框,键入为本文创建的资源组的名称。 在结果列表中选择资源组。

    在工作窗格中显示要删除的资源组列表的屏幕截图。

  3. 选择“删除资源组”。

  4. 系统会要求确认是否删除资源组。 键入资源组的名称进行确认,然后选择“删除”。

    显示需要资源名称才能确认删除的表单的屏幕截图。

片刻之后,将会删除该资源组及其所有资源。

后续步骤

在本快速入门中,你已了解如何使用 Redis 的 Rust 驱动程序在 Azure Cache for Redis 中进行连接和执行操作。