R

Redis 简介

2025-06-09

Redis 简介

什么是 Redis?

Redis 是一个内存键值数据存储系统,您可以将其与应用程序集成,以存储易失性数据。之所以说它易失性,是因为一旦退出 Redis,您存储的所有数据都会丢失。

它的工作原理是将一些值存储在某个键中。稍后你可以请求“给我键‘some_key’的值”。

它支持多种数据类型,如字符串、哈希、列表、集合、位图等……

我需要它吗?

Redis 通常用作缓存机制。例如,假设您的应用程序有一个端点执行一项计算量很大的任务,并向用户返回一个很大的 JSON 数据。如果您对每个请求都重复执行此操作,则很可能会造成客户端-服务器通信的瓶颈。一种常见的解决方案是执行一次操作,然后将结果存储在 Redis 中。下次用户发出相同的请求时,您的应用程序只需检查结果是否已缓存并返回即可。

当然,这种模式要求你遵循一组规则:

每个存储的结果都应该具有唯一的命名空间。在下面的示例中,结果应该根据用户 ID(例如)以及任何其他可以标识两个请求相同的附加参数进行缓存。

您应该为存储在 Redis 中的每个结果强制设置 TTL(生存时间)。15
分钟的 TTL 意味着 15 分钟后,结果将从 Redis 中清除。在下面的示例中,这意味着在初始请求发出 15 分钟后,新的用户请求将再次触发服务器上的繁重计算。这取决于您的应用程序和用户需求,因此请花些时间仔细考虑。

不要过度使用 Redis。这一点很重要。Redis 只适用于某些任务,并非所有任务都适用。请在适当的时候使用合适的数据库。例如,不应将用户凭据和首选项存储在 Redis 中。

如果您正在处理海量数据集,在 Redis 上执行查询时务必格外小心。如果您的应用程序每分钟对 Redis 执行多次读取和/或写入操作,那么一次错误的 Redis 查询(例如,列出当前存在的所有键)可能会导致停机,甚至可能破坏整个应用程序。当然,这取决于应用程序的整体基础架构。

在这篇博文的剩余部分,我将讨论 Redis 支持的主要数据类型以及每种数据类型的基本命令。我将使用 Redis 的 Ruby 实现(您可以在这里找到),并作为示例向您展示如何在 Rails 应用程序中设置 Redis。几乎所有编程语言都有 Redis 的移植版本,并且它们的公共 API 应该非常相似,因此,只需阅读官方代码库中的 README 文件,即可轻松根据您首选的开发环境进行设置。

在 Rails 应用中设置 Redis

只需将 redis 附加到本地 Gemfile 即可

gem 'redis'

然后在您的config/initializer文件夹中创建一个名为的新初始化类redis.rb

Redis.current = Redis.new(host: 'localhost', port: 6379)

您还可以根据配置 Redis 的方式传递其他选项,例如密码、特定 Unix 套接字的路径、驱动程序和特定的数据库名称。有关如何配置 Redis 的更多信息,请查看官方 Ruby 库中的 README 文件。

常规命令

这些命令并不特定于某种数据类型,而是针对任何 redis 键本身

  • 删除密钥
    Redis.current.del('some key')

  • 检查键是否存在
    Redis.current.exists('some key')

  • 获取数据库中的所有键
    Redis.current.keys

!! 警告 !! :请不惜一切代价避免在生产 redis 服务器中运行上述命令,因为此操作具有 O(N) 复杂度,其中 N 是您当前在 Redis 中拥有的键的数量。

  • 在密钥中设置 TTLRedis.current.expire('some key', 5000)

第二个参数是过期时间,以毫秒为单位。这意味着该密钥'some key+将在 5 秒后过期。

  • 重命名密钥Redis.current.rename('some key', 'new key')

如果您不知道或不记得某个键当前保存的是哪种数据结构,您可以让 Redis 通知您:

Redis.current.type('key') => 'String', 'Set', 'Hash', ...

如果您确实想对 Redis 中的所有键执行扫描(例如,检查名称中具有特定模式的键是否存在),正确的方法是使用扫描命令。

例如,假设我们当前的 Redis 数据库包含 10 亿个键,你想知道其中是否有名为 pattern 的键some:cache:key。你不能,我再说一遍,你不能执行该命令Redis.current.keys并遍历返回的集合来查找它。你不仅可能会耗尽应用程序的内存,还可能会搞垮 Redis。

您将使用 scan 来实现这一点。此命令允许您使用游标在数据库中迭代查找键。您为其提供一个初始游标,Redis 将扫描接下来的 N 个键(可配置),然后返回下一个游标(以及已扫描的键),供您在下次调用时使用。

为了正确使用此命令,您应该在 Redis 返回 0 作为下一个游标时停止扫描。这意味着没有其他键可供扫描。在上面的示例中,要查找包含模式 some:cache:key 的键,我们可以按以下方式使用扫描:

Redis.current.scan(0, match: '*some:cache:key*')

模式前后的星号表示“我不关心这个特定模式之前或之后的内容,因此键random:some:cache:key:random会匹配。

例如,第一次调用将返回迭代器 1000,并且所有键都与模式匹配。假设迭代器不为 0,我们可以继续:

Redis.current.scan(1000, match: '*some:cache:key*')

此调用将返回迭代器 10,因此我们继续:

Redis.current.scan(10, match: '*some:cache:key*')

此调用将返回迭代器 0,因此我们知道不再有与此模式匹配的键。毋庸置疑,您应该从每个扫描命令的结果中保存一个已匹配的键的列表。

字符串/整数

在本节中,我们将学习从 redis 存储和检索字符串和整数值的基本操作。

  • 在键中存储新的字符串值
    Redis.current.set('mykey', 'myvalue')

  • 检索键 mykey 的值
    Redis.current.get('mykey') => 'myvalue'

  • 在键中设置新的字符串值,除非它已经存在
    Redis.current.setnx('mykey', 10) => false (because the key 'mykey' already exists)

Redis.current.setnx('another key', 10) => 'OK'

哈希

Redis 中的哈希是一种可以保存多个键值对的数据结构(就像 Ruby 中的哈希一样)

  • 在哈希中创建新的键/值对:
    Redis.current.hset('myhash', 'my hash field', 10)

  • 检索哈希 myhash 中字段 my hash field 的值:
    Redis.current.hget('myhash', 'my hash field')

还有一种方法可以在单个命令中创建具有多个字段的哈希:

Redis.current.hmset('myhash', 'field 1', 'value field 1', 'field 2', 'value field 2', 'field 3', 'value field 3')

这里我展示了字符串的示例,但当然您也可以存储整数,甚至是 json 转储,例如:

Redis.current.hmset('myhash', 'field 3', '{\" key \": \" value \"}')

同样,您也可以在单个命令中检索多个字段的值

Redis.current.hmget('myhash', 'field 2', 'field 3') => {'field 2' => 'value field 2', 'field 3' => 'value field 3'}

  • 从哈希表中删除一个或多个字段Redis.current.hdel('myhash', 'field 2', 'field 3')

检索存储在密钥中的完整哈希值
Redis.current.hgetall('myhash') => {'field 1' => 'value field 1', 'field 2' => 'value field 2', 'field 3' => 'value field 3'}

列表

  • 将新元素添加到列表的前面(添加到列表的开头):
    Redis.current.lpush("mylist", 10)

  • 将新元素附加到列表(添加到列表末尾):
    Redis.current.rpush("mylist", JSON.dump({ some_hash_key: 2}))

  • 从列表中删除元素
    Redis.current.lrem("mylist", 1, 10)

该方法lrem接受三个参数。第一个参数是保存列表的键的名称,第三个参数是我们要从列表中删除的元素,第二个参数是一个整数,它:

  • 当值为 0 时,它将删除列表中所有等于我们要删除的元素的元素。例如,如果列表中有多个值为 10 的元素,调用 Redis.current.lrem("mylist", 0, 10) 将删除列表中所有值为 10 的元素。
  • 当为正数时,将从列表的头部到尾部删除与我们要删除的元素匹配的第一个元素
  • 当为负数时,将删除与我们要删除的元素匹配的第一个元素,从列表尾部开始到头部。
    最后两个选项很有用,例如,如果您想删除列表中给定元素的第一个或最后一个出现的位置

  • 获取列表的元素
    Redis.current.lrange("mylist", 0, -1)

此方法的第二个和第三个参数指定了我们想要的元素范围。当使用 0 和 -1 时,表示我们需要从头到尾的所有元素。如果我们只想要前两个元素,则必须写入Redis.current.lrange("mylist", 0, 1),依此类推。

如果您不知道列表的当前大小:
Redis.current.llen("mylist")

如果想要保留具有唯一元素的数据结构,集合很有用。

  • 向集合中添加新元素Redis.current.sadd("myset", "myelement")

请注意,如果元素“myelement”已存在于集合“myset”中,则会被忽略,因此不会添加

  • 从集合中删除元素
    Redis.current.srem("myset", "myelement")

  • 获取集合的所有当前成员
    Redis.current.smembers("myset")

  • 检查元素是否已存在于集合中
    Redis.current.sismember("myset", "myelement")

最后的想法

这里列出的命令只是一个快速的“速查表”,你可以用它来快速查找 Redis 的最常见用例。完整的命令列表,请查看官方的 Redis 文档。

最后,请注意您使用 Redis 的方式。如果 Redis 与运行应用程序的机器不同,请将每次 Redis 调用视为一次网络请求。此外,请谨慎使用从列表中返回所有内容的命令,例如 smembers 、 lrange 、 hgetall 等。如果您的应用程序非常庞大,您不仅可能会占用过多的内存,还可能暂时阻塞 Redis。务必使用基于迭代的搜索,例如 scan 。

感谢阅读!

鏂囩珷鏉ユ簮锛�https://dev.to/luispcosta/redis---an-introduction-3lof
PREV
构建您的第一个语音驱动的Web应用程序
NEXT
使用 Node.JS 为 Python 脚本实现 React UI