Redis数据类型和抽象介绍

 

Redis数据类型和抽象介绍

红色不是平原键值存储,它实际上是一个数据结构服务器支持不同类型的价值观。这意味着,在传统的键值存储中,您将字符串键与字符串值相关联,但在Redis中,值不仅限于一个简单的字符串,还可以包含更复杂的数据结构。以下是Redis支持的所有数据结构的列表,本教程将分别讨论这些结构:

  • 二进制安全字符串。
  • List:根据插入顺序排序的字符串元素集合。他们基本上是链接列表.
  • SET:唯一的、未排序的字符串元素的集合。
  • 排序集,类似于集合,但每个字符串元素都与浮点数值相关联,称为得分。元素总是按照它们的分数排序,所以不像集合一样,可以检索一系列元素(例如,您可能会问:给我前10位,或者最后10位)。
  • 散列,它是由与值关联的字段组成的映射。字段和值都是字符串。这非常类似于Ruby或Python散列。
  • 位数组(或简单的位图):可以使用特殊命令来处理字符串值,如位数组:您可以设置和清除单个位,计数所有设置为1的位,找到第一个集或未设置位,等等。
  • 超级Logs:这是一种概率数据结构,用于估计集合的基数。别害怕,这比看上去简单.请参阅本教程的HyperLogLog部分后面的内容。
  • 流:仅附加提供抽象日志数据类型的类似于映射的条目集合。它们被深埋在Redis流简介.

了解这些数据类型是如何工作的,以及如何使用这些数据类型来解决给定的问题。命令引用因此,本文档是关于Redis数据类型及其最常见模式的速成课程。

对于所有示例,我们将使用redis-cli实用工具,一个简单但方便的命令行实用工具,用于向Redis服务器发出命令。

红键

Redis键是二进制安全的,这意味着您可以使用任何二进制序列作为键,从字符串“foo”到JPEG文件的内容。空字符串也是一个有效的键。

还有一些关于钥匙的其他规则:

  • 很长的钥匙不是个好主意。例如,一个1024字节的键不仅是内存方面的错误想法,还因为在DataSet中查找键可能需要几个昂贵的键比较。即使手头的任务是匹配大值的存在,哈希(例如使用SHA 1)也是一个更好的主意,特别是从内存和带宽的角度来看。
  • 很短的键往往不是个好主意。如果您可以编写“user:1000:关注者”,那么将“u1000flw”作为键编写是没有什么意义的。后者的可读性更强,与键对象本身和Value对象使用的空间相比,添加的空间更小。虽然短键显然会消耗更少的内存,但您的工作是找到合适的平衡。
  • 试着坚持模式。例如,“object-type:id”是个好主意,就像在“user:1000”中一样。点或破折号常用于多词字段,如“注释:1234:回复”或“注释:1234:回复-to”。
  • 允许的最大密钥大小为512 MB。

红串

Redis字符串类型是可以与Redis键关联的最简单的值类型。它是memcached中唯一的数据类型,所以新手在Redis中使用它也是非常自然的。

因为Redis键是字符串,所以当我们将字符串类型也用作值时,我们将字符串映射到另一个字符串。字符串数据类型对于许多用例非常有用,比如缓存HTML片段或页面。

让我们来玩一下字符串类型,使用redis-cli(所有示例将通过redis-cli在本教程中)。

> set mykey somevalue
OK
> get mykey
"somevalue"

如您所见,使用到达命令是我们设置和检索字符串值的方式。请注意将替换已存储到键中的任何现有值,即使键与非字符串值相关联,如果键已经存在则也是如此。所以执行任务。

值可以是各种字符串(包括二进制数据),例如,您可以在值中存储jpeg图像。值不能大于512 MB。

这个命令有一些有趣的选项,这些选项作为附加参数提供。例如,我可能会问如果键已经存在,则失败,或者相反,只有当键已经存在时,它才会成功:

> set mykey newval nx
(nil)
> set mykey newval xx
OK

即使字符串是Redis的基本值,您也可以使用它们执行有趣的操作。例如,一个是原子增量:

> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152

这个英格尔命令将字符串值解析为整数,将其递增1,最后将获得的值设置为新值。还有其他类似的命令,如INCRBY德克尔DECRBY。在内部,它总是以一种稍微不同的方式执行相同的命令。

这意味着INGR是原子的吗?即使是多个客户端使用相同的密钥发出incr,也永远不会进入争用状态。例如,客户端1读取“10”,客户端2同时读取“10”,增量为11,并将新值设置为11。最终值始终为12,读取增量集操作将在所有其他客户端不同时执行命令时执行。

有许多用于对字符串进行操作的命令。例如,GETSET命令设置一个新值的键,返回旧值作为结果。例如,如果系统使用英格尔每次你的网站收到一个新的访问者。您可能希望每小时收集一次此信息,而不会丢失一个增量。你可以的GETSET键,为其分配“0”的新值,并返回旧值。

在单个命令中设置或检索多个键的值的能力对于减少延迟也很有用。由于这个原因,有MSETMGET命令:

> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"

什么时候MGET使用时,Redis将返回一个值数组。

更改和查询密钥空间

有些命令没有在特定类型上定义,但对于与键空间进行交互很有用,因此,可以与任何类型的键一起使用。

例如,存在命令返回1或0以指示给定的键是否存在于数据库中,而德尔命令删除键和相关值,不管该值是什么。

> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0

在这些例子中,您还可以看到德尔它本身返回1或0,这取决于键是否被移除(它是否存在)(没有该名称的密钥)。

有许多与键空间相关的命令,但上述两个命令与类型命令,该命令返回存储在指定键中的值的类型:

> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none

红宝石过期:生命时间有限的钥匙

在继续处理更复杂的数据结构之前,我们需要讨论另一个功能,它可以不考虑值类型,并被称为红宝石到期。基本上,您可以为一个键设置一个超时,这是一个有限的生存时间。当存活时间流逝时,密钥将自动销毁,就像用户调用德尔用钥匙指挥。

关于Redis的几个快速信息到期:

  • 可以使用秒或毫秒的精度来设置它们。
  • 然而,过期时间分辨率总是1毫秒。
  • 有关过期的信息将复制并保存在磁盘上,当您的Redis服务器仍然停止时,时间实际上会过去(这意味着Redis保存密钥过期的日期)。

设置过期非常简单:

> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)

钥匙在两个人之间消失了到达呼叫,因为第二个呼叫被延迟超过5秒。在上面的示例中,我们使用了过期为了设置过期(也可以使用它来设置另一个已具有过期的密钥),如坚持可用于删除过期并使密钥永久持久)。但是,我们也可以使用其他Redis命令创建带ExchangeWith的键。例如,使用备选方案:

> set key 100 ex 10
OK
> ttl key
(integer) 9

上面的示例设置了一个具有字符串值的键。100有十秒的过期时间。后来TTL命令的调用,以检查剩余的时间来保存密钥。

为了设置和检查过期时间(毫秒),请检查PEXPIREPTTL命令和各种选择。

红宝石名单

要解释列表数据类型,最好从一些理论开始,作为术语列单信息技术人员经常以不适当的方式使用。例如,“Python列表”不是名称所暗示的(链接列表),而是数组(实际上在Ruby中相同的数据类型称为Array)。

从一个非常普遍的角度来看,列表只是一个有序元素的序列:10,20,1,2,3是一个列表。但是,使用Array实现的列表的属性与使用链表.

REDIS列表是通过链接列表实现的。这意味着,即使列表中有数以百万计的元素,也会执行在列表的头或尾中添加新元素的操作。恒定时间。控件添加新元素的速度。LPUSH命令指向一个包含10个元素的列表的头,这与将一个元素添加到包含1000万个元素的列表头部相同。

缺点是什么?访问元素按指数在用Array(常数时间索引访问)实现的列表中,速度非常快,而在由链接列表实现的列表中(在该列表中,操作需要与所访问元素的索引成比例的工作量),速度不太快。

Redis列表是用链接列表实现的,因为对于数据库系统来说,能够以非常快的方式将元素添加到非常长的列表中是至关重要的。另一个强大的优势,就像您稍后会看到的,是Redis列表可以在恒定的时间内以恒定的长度获取。

当快速访问大型元素集合的中部非常重要时,可以使用不同的数据结构,称为排序集。排序集将在本教程后面讨论。

使用Redis列表的第一步

这个LPUSH命令将一个新元素添加到列表的左边(头部),而RPUSH命令在右边(尾部)的列表中添加一个新元素。最后朗格命令从列表中提取元素的范围:

> rpush mylist A
(integer) 1
> rpush mylist B
(integer) 2
> lpush mylist first
(integer) 3
> lrange mylist 0 -1
1) "first"
2) "A"
3) "B"

请注意朗格接受两个索引,即要返回的范围的第一个和最后一个元素。这两个索引都可以是负的,告诉Redis从末尾开始计数:so-1是最后一个元素,-2是列表的倒数第二元素,依此类推。

如你所见RPUSH追加列表右侧的元素,而最终LPUSH将元素追加到左侧。

这两个命令都是可变命令,这意味着您可以在一个调用中将多个元素推入列表中:

> rpush mylist 1 2 3 4 5 "foo bar"
(integer) 9
> lrange mylist 0 -1
1) "first"
2) "A"
3) "B"
4) "1"
5) "2"
6) "3"
7) "4"
8) "5"
9) "foo bar"

在Redis列表上定义的一个重要操作是POP元素。弹出元素是同时从列表中检索元素和从列表中删除元素的操作。您可以从左边和右边弹出元素,类似于如何在列表的两边推送元素:

> rpush mylist a b c
(integer) 3
> rpop mylist
"c"
> rpop mylist
"b"
> rpop mylist
"a"

我们添加了三个元素并弹出了三个元素,因此在这个命令序列的末尾,列表是空的,没有更多的元素可以弹出。如果我们尝试弹出另一个元素,这就是我们得到的结果:

> rpop mylist
(nil)

redis返回一个空值,以指示列表中没有元素。

列表的通用用例

列表对于许多任务很有用,两个非常有代表性的用例如下:

  • 记住用户在社交网络上发布的最新更新。
  • 进程之间的通信,使用使用者-生产者模式(生产者将项目推入列表)和使用者(通常是工人)使用这些项并执行操作。Redis有特殊的列表命令来使这个用例更加可靠和高效。

例如,两个流行的Ruby库雷克塞德基克使用隐藏项下的Redis列表来实现后台作业。

流行的Twitter社交网络获取最新的推特由用户发布到Redis列表。

为了一步一步地描述一个常见的用例,假设您的主页显示了在照片共享社交网络中发布的最新照片,并且希望加快访问速度。

  • 每次用户发布新照片时,我们都会将其ID添加到以下列表中LPUSH.
  • 当用户访问主页时,我们使用LRANGE 0 9为了得到最新的10条贴出的物品。

上限列表

在许多用例中,我们只想使用列表来存储最新项目,不管它们是什么:社交网络更新、日志或其他任何东西。

Redis允许我们使用列表作为有上限的集合,只需要记住最新的N项,并使用LTRIM命令。

这个LTRIM命令类似于朗格,但是而不是显示指定的元素范围。它将此范围设置为新的列表值。在给定范围之外的所有元素都被移除。

举一个例子可以更清楚地说明:

> rpush mylist 1 2 3 4 5
(integer) 5
> ltrim mylist 0 2
OK
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"

上述LTRIM命令告诉Redis只获取索引0到2的列表元素,其他所有内容都将被丢弃。这允许一种非常简单但有用的模式:执行列表推送操作+将列表修剪操作放在一起,以便添加新元素并丢弃超过限制的元素:

LPUSH mylist <some element>
LTRIM mylist 0 999

上面的组合添加了一个新元素,并且只接受列表中的1000个最新元素。带着朗格您可以访问顶部的项目,而不需要记住非常老的数据。

注:同时朗格在技术上是O(N)命令,访问指向列表的头部或尾部的小范围是一个恒定的时间操作。

阻止列表上的操作

列表有一个特殊的特性,使它们适合实现队列,并且通常作为进程间通信系统的一个构建块:阻塞操作。

假设您希望使用一个进程将项目推入列表中,并使用不同的流程来实际处理这些项。这是通常的生产者/消费者设置,可以通过以下简单方式实现:

  • 要将项目推入列表,生产者将调用LPUSH.
  • 要从列表中提取/处理项,使用者将调用RPOP.

但是,有时列表可能是空的,没有什么可处理的,所以RPOP只返回NULL。在这种情况下,消费者被迫等待一段时间,然后再用RPOP。这叫做轮询,在这种情况下不是一个好主意,因为它有几个缺点:

  1. 强制Redis和客户端处理无用的命令(当列表为空时,所有请求都不会完成实际的工作,它们只会返回NULL)。
  2. 为项目的处理添加延迟,因为在工作人员收到NULL后,它会等待一段时间。为了使延迟更小,我们可以减少呼叫之间的等待时间。RPOP,具有放大问题1的效果,即对Redis的更多无用调用。

因此Redis实现了名为BRPOPBLPOP的版本RPOPLPOP如果列表为空,则可以阻塞:只有在向列表中添加新元素或达到用户指定的超时时,它们才会返回给调用方。

这是一个例子BRPOP我们可以给工人打电话:

> brpop tasks 5
1) "tasks"
2) "do_something"

它的意思是:“等待列表中的元素。tasks,但如果5秒后没有可用的元素,则返回“。

注意,您可以使用0作为超时来永远等待元素,还可以指定多个列表,而不仅仅是一个列表,以便同时等待多个列表,并在第一个列表收到元素时得到通知。

有几件事要注意BRPOP:

  1. 客户端以有序的方式服务:阻止等待列表的第一个客户端,在某个元素被其他客户端推送时首先服务,依此类推。
  2. 返回值与RPOP它是一个双元素数组,因为它还包括键的名称,因为BRPOPBLPOP能够阻止从多个列表中等待元素。
  3. 如果到达超时,则返回NULL。

关于列表和阻塞操作,您应该了解更多的事情。我们建议您多阅读以下内容:

  • 可以使用以下方法构建更安全的队列或旋转队列RPOPLPUSH.
  • 还有一个命令的阻塞变体,称为BRPOPLPUSH.

自动创建和移除键

到目前为止,在我们的示例中,我们不必在推送元素之前创建空列表,也不必在元素中不再有元素时删除空列表。当列表保持为空时,Redis有责任删除键,或者在键不存在的情况下创建一个空列表,并且我们试图向其中添加元素,例如,使用LPUSH.

这并不限于列表,它适用于由多个元素组成的所有Redis数据类型--流、集、排序集和散列。

基本上,我们可以用三个规则来总结行为:

  1. 当我们向聚合数据类型添加元素时,如果目标键不存在,则在添加元素之前创建一个空聚合数据类型。
  2. 当我们从聚合数据类型中删除元素时,如果该值保持为空,则该键将自动销毁。Stream数据类型是此规则的唯一例外。
  3. 调用只读命令,如伊伦(返回列表的长度),或使用空键删除元素的写命令总是产生相同的结果,就像该键持有命令希望查找的类型的空聚合类型一样。

规则1的例子:

> del mylist
(integer) 1
> lpush mylist 1 2 3
(integer) 3

但是,如果存在键,则不能对错误类型执行操作:

> set foo bar
OK
> lpush foo 1 2 3
(error) WRONGTYPE Operation against a key holding the wrong kind of value
> type foo
string

规则2的例子:

> lpush mylist 1 2 3
(integer) 3
> exists mylist
(integer) 1
> lpop mylist
"3"
> lpop mylist
"2"
> lpop mylist
"1"
> exists mylist
(integer) 0

在弹出所有元素之后,键就不再存在了。

规则3的例子:

> del mylist
(integer) 0
> llen mylist
(integer) 0
> lpop mylist
(nil)

红哈希

redis散列看起来就像人们所期望的“散列”(散列),其中包含字段值对:

> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username
"antirez"
> hget user:1000 birthyear
"1977"
> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

而散列表示则很方便。对象实际上,您可以在散列中放置的字段数没有实际限制(除了可用内存),因此您可以在应用程序中以多种不同的方式使用散列。

命令HMSET设置散列的多个字段,同时赫格检索单个字段。HMGET类似于赫格但是返回一个值数组:

> hmget user:1000 username birthyear no-such-field
1) "antirez"
2) "1977"
3) (nil)

有些命令也可以对单个字段执行操作,如辛尼:

> hincrby user:1000 birthyear 10
(integer) 1987
> hincrby user:1000 birthyear 10
(integer) 1997

你可以找到文档中哈希命令的完整列表.

值得注意的是,小散列(即具有小值的几个元素)在内存中以特殊方式编码,从而使它们具有非常高的内存效率。

Redis集

redis集是字符串的无序集合。这个赛德命令向集合添加新元素。还可以对集合执行许多其他操作,比如测试给定元素是否已经存在,执行多个集合之间的交叉、合并或差异等等。

> sadd myset 1 2 3
(integer) 3
> smembers myset
1. 3
2. 1
3. 2

在这里,我添加了三个元素到我的集合,并告诉Redis返回所有的元素。正如您所看到的,它们没有排序--Redis可以在每次调用时以任何顺序返回元素,因为在元素排序方面没有与用户的契约。

redis有测试成员资格的命令。例如,检查元素是否存在:

> sismember myset 3
(integer) 1
> sismember myset 30
(integer) 0

“3”是组中的一员,而“30”则不是。

集合很好地表达了对象之间的关系。例如,我们可以很容易地使用SET来实现标记。

对这个问题建模的一个简单方法是为我们想要标记的每个对象设置一个集合。集合包含与对象关联的标记的ID。

一个例子是在新闻文章上加上标签。如果使用标记1、2、5和77标记文章ID 1000,则集合可以将这些标记ID与新闻项目关联起来:

> sadd news:1000:tags 1 2 5 77
(integer) 4

我们也可能希望有一个反比关系:带有给定标签的所有新闻的列表:

> sadd tag:1:news 1000
(integer) 1
> sadd tag:2:news 1000
(integer) 1
> sadd tag:5:news 1000
(integer) 1
> sadd tag:77:news 1000
(integer) 1

要获取给定对象的所有标记非常简单:

> smembers news:1000:tags
1. 5
2. 1
3. 77
4. 2

注意:在这个示例中,我们假设您有另一个数据结构,例如Redis散列,它将标记ID映射到标记名。

还有其他一些不简单的操作,使用正确的Redis命令仍然很容易实现。例如,我们可能需要一个带有标记1、2、10和27的所有对象的列表。我们可以使用烧结矿命令,它执行不同集合之间的交集。我们可以使用:

> sinter tag:1:news tag:2:news tag:10:news tag:27:news
... results here ...

除了交集之外,您还可以执行联合、差分、提取一个随机元素,等等。

提取元素的命令被调用SPOP,并且可以方便地模拟某些问题。例如,为了实现基于网络的扑克游戏,您可能需要用一组集合来表示您的牌盘。假设我们使用一个字符前缀来表示(C)Lubs,(D)IAMES,(H)EATS,(S)PADES:

>  sadd deck C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 CJ CQ CK
   D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 DJ DQ DK H1 H2 H3
   H4 H5 H6 H7 H8 H9 H10 HJ HQ HK S1 S2 S3 S4 S5 S6
   S7 S8 S9 S10 SJ SQ SK
   (integer) 52

现在我们想为每位玩家提供5张卡。这个SPOP命令删除一个随机元素,并将其返回给客户端,因此在本例中,它是完美的操作。

但是,如果我们把它直接用在我们的牌上,那么在下一场比赛中,我们需要再次填充扑克牌,这可能并不理想。因此,首先,我们可以制作存储在deck键进入game:1:deck钥匙。

这是使用苏尼斯特,它通常执行多个集合之间的合并,并将结果存储到另一个集合中。但是,由于单一集合的结合本身,我可以复制我的甲板与:

> sunionstore game:1:deck deck
(integer) 52

现在我准备为第一位玩家提供五张卡片:

> spop game:1:deck
"C6"
> spop game:1:deck
"CQ"
> spop game:1:deck
"D1"
> spop game:1:deck
"CJ"
> spop game:1:deck
"SJ"

一副千斤顶,不是很好.

现在是引入set命令的好时机,它提供了集合中元素的数量。这常被称为集的基数在集合论的上下文中,因此Redis命令被调用浮渣.

> scard game:1:deck
(integer) 47

数学计算:52-5=47.

当您只需要获取随机元素而不将它们从集合中移除时,斯兰德梅尔命令适合该任务。它还具有返回重复和非重复元素的能力。

Redis排序集

排序集是一种数据类型,类似于集合和散列之间的混合。与集合一样,排序集是由唯一的、不重复的字符串元素组成的,因此在某种意义上,排序集也是一个集合。

但是,虽然集合中的元素没有排序,但排序集中的每个元素都与一个浮点值相关联,称为得分(这就是为什么类型也类似于哈希,因为每个元素都映射到一个值)。

此外,排序集中的元素包括井然有序(因此它们不是根据请求排序的,Order是用于表示排序集的数据结构的一个特性)。它们是根据下列规则订购的:

  • 如果A和B是两个分数不同的元素,那么A>B如果A分数是>B得分。
  • 如果A和B的分数完全相同,则A>B,如果A字符串在字典上大于B字符串。A和B字符串不能相等,因为排序集只有唯一的元素。

让我们从一个简单的例子开始,添加一些选定的黑客名字作为排序集合元素,他们的出生年份作为“分数”。

> zadd hackers 1940 "Alan Kay"
(integer) 1
> zadd hackers 1957 "Sophie Wilson"
(integer) 1
> zadd hackers 1953 "Richard Stallman"
(integer) 1
> zadd hackers 1949 "Anita Borg"
(integer) 1
> zadd hackers 1965 "Yukihiro Matsumoto"
(integer) 1
> zadd hackers 1914 "Hedy Lamarr"
(integer) 1
> zadd hackers 1916 "Claude Shannon"
(integer) 1
> zadd hackers 1969 "Linus Torvalds"
(integer) 1
> zadd hackers 1912 "Alan Turing"
(integer) 1

如你所见ZADD类似于赛德,但需要附加一个参数(放在要添加的元素之前),即得分。ZADD也是可变的,所以您可以自由地指定多个得分值对,即使这在上面的示例中没有使用。

使用排序集,返回按其出生年份排序的黑客列表是很简单的,因为实际上他们已经被分类了.

实现注意:排序集是通过包含跳过列表和哈希表的双端口数据结构实现的,因此每次添加元素Redis时,都会执行O(log(N))行动。这很好,但是当我们要求排序元素时,Redis根本不需要做任何工作,它已经被排序了:

> zrange hackers 0 -1
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"
6) "Richard Stallman"
7) "Sophie Wilson"
8) "Yukihiro Matsumoto"
9) "Linus Torvalds"

注意:0和-1意味着从元素索引0到最后一个元素(-1在这里工作,就像在朗格指挥)。

如果我想以相反的方式订购它们,从小到老呢?使用雷夫朗格(ZREVRANGE)而不是ZRANGE:

> zrevrange hackers 0 -1
1) "Linus Torvalds"
2) "Yukihiro Matsumoto"
3) "Sophie Wilson"
4) "Richard Stallman"
5) "Anita Borg"
6) "Alan Kay"
7) "Claude Shannon"
8) "Hedy Lamarr"
9) "Alan Turing"

也可以返回分数,使用WITHSCORES论点:

> zrange hackers 0 -1 withscores
1) "Alan Turing"
2) "1912"
3) "Hedy Lamarr"
4) "1914"
5) "Claude Shannon"
6) "1916"
7) "Alan Kay"
8) "1940"
9) "Anita Borg"
10) "1949"
11) "Richard Stallman"
12) "1953"
13) "Sophie Wilson"
14) "1957"
15) "Yukihiro Matsumoto"
16) "1965"
17) "Linus Torvalds"
18) "1969"

按范围操作

排序集比这更强大。他们可以在靶场上操作。让我们把所有出生到1950年的人都包括在内。我们使用兹朗贝斯克命令:

> zrangebyscore hackers -inf 1950
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"

我们要求Redis返回所有元素,在负无穷大和1950年之间得分(这两个极端都包括在内)。

还可以删除元素的范围。让我们把1940年到1960年间出生的所有黑客都从分类组中移除:

> zremrangebyscore hackers 1940 1960
(integer) 4

ZREMRANGEBYSCORE可能不是最好的命令名,但它可能非常有用,并返回已删除元素的数量。

为排序集元素定义的另一个非常有用的操作是GET秩操作。可以询问元素在有序元素集合中的位置。

> zrank hackers "Anita Borg"
(integer) 4

这个ZREVRANK命令也可用,以获得排序,考虑元素排序的降序方式。

词典学分数

在Redis 2.8的最新版本中,引入了一个新特性,允许按字典顺序获取范围,假设排序集中的元素都以相同的分数插入(元素与C比较)memcmp函数,因此保证没有排序规则,并且每个Redis实例都将使用相同的输出进行答复)。

使用字典范围操作的主要命令有:ZRANGEBYLEX雷夫朗贝乐(ZREVRANGEBYLEX)雷姆朗贝莱(ZREMRANGEBYLEX)ZLEXCOUNT.

例如,让我们再次添加我们的著名黑客列表,但这一次对所有元素使用零分:

> zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0
  "Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon"
  0 "Linus Torvalds" 0 "Alan Turing"

由于排序集的排序规则,它们已经按字典顺序排序:

> zrange hackers 0 -1
1) "Alan Kay"
2) "Alan Turing"
3) "Anita Borg"
4) "Claude Shannon"
5) "Hedy Lamarr"
6) "Linus Torvalds"
7) "Richard Stallman"
8) "Sophie Wilson"
9) "Yukihiro Matsumoto"

使用ZRANGEBYLEX我们可以要求词典编纂范围:

> zrangebylex hackers [B [P
1) "Claude Shannon"
2) "Hedy Lamarr"
3) "Linus Torvalds"

范围可以是包含的或独占的(取决于第一个字符),也可以使用+-弦乐。有关更多信息,请参见文档。

这个特性很重要,因为它允许我们使用排序集作为通用索引。例如,如果要用128位无符号整数参数对元素进行索引,则只需将元素添加到具有相同分数(例如0)的排序集中,但要使用由16字节前缀组成的大端128位数。由于大端字节中的数字(按原始字节顺序排序)实际上也是按数字顺序排列的,所以您可以在128位空间中请求范围,并获得元素的值丢弃前缀。

如果您想在更严肃的演示的上下文中查看该特性,请检查Redis自动完成演示.

更新评分:领导委员会

在切换到下一个主题之前,只需对排序集做最后的说明。排序集的分数可以随时更新。只是打电话ZADD针对已包含在排序集中的元素,将使用O(log(N))时间复杂性。因此,当有大量更新时,排序集是合适的。

由于这一特点,一个常见的用例是领导委员会。典型的应用程序是一款facebook游戏,在游戏中,你结合了将用户按高分排序的能力,再加上获取排名操作,以显示排名前N的用户,以及在领导委员会中的用户排名(例如,“您是这里的#4932最佳得分”)。

位图

位图不是实际的数据类型,而是定义在字符串类型上的一组面向位的操作。由于字符串是二进制安全块,其最大长度为512 MB,因此它们适合设置为2。32不同的部分。

比特操作分为两组:固定时间的单比特操作,如将位设置为1或0,或获取其值,以及对比特组的操作,例如,计算给定比特范围内的集合位数(例如,人口计数)。

位图的最大优点之一是,它们在存储信息时往往节省了极大的空间。例如,在使用增量用户ID表示不同用户的系统中,只需使用512 MB内存就可以记住单个比特信息(例如,知道用户是否想接收时事通讯)。

位设置并使用SETBITGETBIT命令:

> setbit key 10 1
(integer) 1
> getbit key 10
(integer) 1
> getbit key 11
(integer) 0

这个SETBIT命令的第一个参数是位数,第二个参数是要将位设置为1或0的值。如果寻址位在当前字符串长度之外,则该命令会自动扩大字符串。

GETBIT只返回指定索引处位的值。超出范围的位(寻址位于存储在目标键中的字符串长度之外的位)总是被认为是零。

在一组位上有三个操作命令:

  1. BITOP执行不同字符串之间的逐位操作。提供的操作是AND、OR、XOR和NOT。
  2. BITCOUNT执行人口计数,报告设置为1的位数。
  3. Bitpos查找指定值为0或1的第一个位。

双管齐下BitposBITCOUNT可以使用字符串的字节范围进行操作,而不是运行字符串的整个长度。下面是一个简单的例子BITCOUNT呼叫:

> setbit key 0 1
(integer) 0
> setbit key 100 1
(integer) 0
> bitcount key
(integer) 2

位图的常用用例如下:

  • 各种实时分析。
  • 存储与对象ID关联的空间高效但高性能的布尔信息。

例如,假设您想知道网站用户每天访问时间最长的一段时间。您从零开始计算日数,也就是您将网站公之于众的那一天,并将其设置为SETBIT每次用户访问网站。作为位索引,您只需使用当前的Unix时间,减去初始偏移量,然后除以一天中的秒数(通常为3600*24)。

这样,每个用户都有一个包含每天访问信息的小字符串。带着BITCOUNT可以轻松地获得给定用户访问网站的天数,而只需几天。Bitpos调用,或者只是获取和分析位图客户端,可以轻松地计算最长的条纹。

将位图分割成多个键是很简单的,例如,为了对数据集进行切分,而且通常情况下,最好避免使用大键。要将位图拆分成不同的键,而不是将所有位设置为键,一个简单的策略就是存储每个键的M位,然后用bit-number/M密钥内的第N位地址bit-number MOD M.

超级Logs

HyperLoglog是一种用于计数唯一事物的概率数据结构(从技术上讲,这是指估计集合的基数)。通常,计算唯一项目需要使用与要计数的项目数量成比例的内存量,因为您需要记住您在过去见过的元素,以避免多次计算它们。然而,有一组算法可以用内存来换取精度:以一个标准错误的估计度量结束,在Redis实现的情况下,这个误差小于1%。这个算法的神奇之处在于,您不再需要使用与计数项的数量成比例的内存量,而是可以使用常量的内存!在最坏的情况下,可以使用12k字节,如果您的HyperLoglog(我们从现在起只称它们为HLL)所见的元素非常少,则会少得多。

Redis中的hls虽然在技术上是一种不同的数据结构,但被编码为Redis字符串,因此您可以调用到达序列化HLL,以及将其反序列化回服务器。

从概念上讲,HLL API就像使用SET来执行相同的任务一样。你会赛德将每一个观察到的元素放入一个集合,并使用浮渣检查集合内的元素数,这些元素是唯一的,因为赛德不会重新添加现有元素。

而你不是真的添加项目由于数据结构只包含不包含实际元素的状态,因此API是相同的:

  • 每次看到新元素时,都会将其添加到PFADD.
  • 每次要检索唯一元素的当前近似值时,带着PFADD到目前为止,您使用的是PFCOUNT.

    > pfadd hll a b c d
    (integer) 1
    > pfcount hll
    (integer) 4
    

这种数据结构的用例是计算用户每天在搜索表单中执行的唯一查询。

Redis也可以执行Hlls的联合,请检查完整文件想了解更多信息。

其他显著特征

Redis API中还有其他一些重要的东西不能在本文档的上下文中进行探讨,但值得您注意:

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值