Redis快速教程

Redis 简介

Redis是一款以键值对形式保存在内存中的数据存储,您可以将其与应用程序集成以存储易失性数据。 必须注意它是不稳定的,因为一旦你退出Redis,你存储的所有数据都将丢失。

它通过在键(key)中存储一些值(value)来工作。

它支持多种数据类型,如strings, hashes, lists, sets, bitmaps等等。

Redis 作用

Redis通常用作缓存机制。 例如,假设你的应用程序有一个端点执行一个计算繁重的任务,并向用户返回一个大的json。 如果您对每个请求反复重复这项工作,您很可能会在您的客户端 - 服务器通信中引入瓶颈。 一个常用的解决方案是执行一次工作,然后将结果存储在Redis中。 用户下一次发出相同的请求时,应用程序只检查结果是否被缓存并返回。

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

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

您应该在您存储在Redis中的每个结果中强制执行TTL(time to live生存时间)。

15分钟的TTL意味着15分钟后,结果从Redis中消失。这意味着在初始请求15分钟后,新的用户请求会再次触发服务器上的繁重计算。这取决于您的应用程序和用户需求,因此需要花点时间思考这个问题。

不要过度使用Redis。这个很重要。 Redis对于某些任务非常有用,而不是所有的任务。适当时使用适当的数据库。例如,您不应将用户凭据和首选项存储在Redis中。

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

对于本博客文章剩下的部分,我将讨论Redis支持的主要数据类型以及各自的基本命令。我将使用Redis的Ruby实现(您可以在这里找到这些实现),并向您展示如何在Rails应用程序中设置Redis。几乎所有的编程语言都有Redis的端口,在这些语言之间公共的API应该非常相似,因此,通过读取官方存储库中的README文件为您偏好的开发环境配置redis应该是很简单的事情。

在Rails应用程序中设置Redis

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

    gem 'redis'

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

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

您还可以传递其他选项,例如密码、特定unix套接字的路径、驱动程序和特定数据库名称,具体取决于您如何配置redis。 在官方的ruby gem上查看README文件,了解更多关于如何配置redis的信息。

常用命令

这些命令不是特定于数据类型的命令,而是任何Redis密钥本身

    ·删除密钥

    Redis.current.del('some key')

    ·检查密钥是否存在

    Redis.current.exists('some key')

    ·获取数据库中的所有密钥

    Redis.current.keys

!警告 !! :禁止不惜一切代价在生产Redis服务器上运行上面的命令,因为此操作具有O(N)复杂性,其中N是您在Redis中当前拥有的密钥数量。

    ·在密钥中设置TTL    

    Redis.current.expire('some key', 5000)    

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

    ·重命名一个密钥

    Redis.current.rename('some key', 'new key')

如果您不知道或不记得某个键当前拥有哪种数据结构,则可以要求redis通知您:

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

如果您确实想要扫描Redis中的所有密钥(例如,要检查名称中是否存在特定模式的密钥),则正确的方法是使用scan命令。

举个例子,假设我们当前的Redis数据库拥有10亿个密钥,并且您想知道是否存在具有名称模式some:cache:key的任一密钥。再强调一下,您不要执行Redis.current.keys命令并遍历返回的集合来查找它。这样你不但可能会杀死你的应用程序内存,而且你也可能会杀死Redis。

scan命令允许您使用游标反复查找数据库中的键。您为它提供了一个初始光标,redis将扫描以下N个键(可配置),然后返回您在下一次调用中应使用的下一个光标(以及扫描的键)。

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

    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,所以我们知道没有更多的键匹配这个模式。不言而喻,您应该保存每个扫描命令的结果,将匹配的键的组成一个列表。

Strings / Integers(字符串/整数)    

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

    ·将新的字符串值存储在密钥中

    Redis.current.set('mykey', 'myvalue')

    ·检索密钥mykey的值

    Redis.current.get('mykey') => 'myvalue'

    ·在一个键中设置一个新的字符串值,保证键值之前不存在

    Redis.current.setnx('mykey', 10) => false(因为'mykey'键已经存在)

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

Hashes(哈希)

Redis中的hash是一个数据结构,它可以包含几个键 - 值对(就像Ruby中的hash)

    ·在哈希myhash中创建一个新的键/值对:

    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'}

Lists(列表)

    ·在列表中添加一个新元素(添加到列表的开头)

    Redis.current.lpush("mylist", 10)

    ·追加一个新元素到列表中(添加到列表的末尾)

    Redis.current.rpush("mylist", JSON.dump({ some_hash_key: 2}))

    ·从列表中删除元素

    Redis.current.lrem("mylist", 1, 10)

lrem方法接受三个参数。第一个参数是保存列表的键的名称,第三个参数是我们想要从列表中删除的元素,第二个参数是一个整数且符合以下情况:

    ·当为0时,它将删除列表中与我们要移除的元素相等的所有元素。例如,如果我们在列表中调用Redis.current.lrem(“mylist”,0,10)的值为10的几个元素将删除列表中值为10的所有元素

    ·当为正数时,将移除与我们想要移除的元素相匹配的第一个元素,从列表头到尾部

    ·当为负数时,将移除与我们想要移除的元素匹配的第一个元素,从列表的尾部开始到头部。例如,如果要删除列表中给定元素的第一个或最后一个元素,最后两个选项很有用

    ·获取列表的元素

    Redis.current.lrange("mylist", 0, -1)

这个方法的第二个和第三个参数指定了我们想要的元素的范围。当使用0和-1时,这意味着我们需要从开始到结束的所有元素。如果我们只想要前两个元素,我们必须编写Redis.current.lrange("mylist", 0, 1)等等。

    如果您不知道列表的当前大小:

    Redis.current.llen("mylist")

Sets(集合)

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

    ·向集合添加新元素

    Redis.current.sadd("myset", "myelement")

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

    ·从集合中删除元素

    Redis.current.srem("myset", "myelement")

    ·获取集合当前的所有成员

    Redis.current.smembers("myset")

    ·检查一个元素是否已经在一个集合中

    Redis.current.sismember("myset", "myelement")

结束语

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

最后,请注意你正在如何使用redis。如果redis与运行应用程序的机器不在同一台机器上,请考虑每个redis调用都是网络请求。另外,要非常小心使用从列表中返回所有内容的命令,例如smembers,lrange,hgetall等。如果您的应用程序非常大,您可能不仅会泛滥您的应用程序内存,还可能阻塞redis一段时间。注意始终使用基于迭代的搜索,如scan。

谢谢阅读!

本文翻译自https://dev.to/luispcosta/redis---an-introduction-3lof,作者将其翻译为中文并排版,方便国内读者学习使用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容