Redis数据类型和常用命令,看这篇就够了

    技术2024-06-11  82

    Redis不是简单的键值存储,它实际上是一个数据结构服务器,支持不同类型的值。这意味着在传统键值存储中,您将字符串键与字符串值相关联,而在Redis中,该值不仅限于简单的字符串,还可以容纳更复杂的数据结构。

    Redis键

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

    redis中,用:表示分层结构,如 object-type:id

    Redis 数据类型

    Redis Strings

    这是最简单Redis类型。如果你只用这种类型,Redis就像一个可以持久化的memcached服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失)。 Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。

    使用Redis Strings,用SET command 和 GET command来设置和获取字符串值。

    例:

    127.0.0.1:6379> set onekey hello OK 127.0.0.1:6379> get onekey "hello"

    当我们的key已经存在,再使用set命令,会用新值替换掉新值

    例:

    127.0.0.1:6379> set onekey hello OK 127.0.0.1:6379> get onekey "hello" 127.0.0.1:6379> set onekey update OK 127.0.0.1:6379> get onekey "update"

    值可以是任何种类的字符串(包括二进制数据),例如你可以在一个键下保存一副jpeg图片。值的长度不能超过512 MB。

    我们可以在set命令后加一个nx,当key存在时SET会失败,只有当key不存在时它只会成功。

    例:

    127.0.0.1:6379> get onekey "update" 127.0.0.1:6379> set onekey new nx (nil)

    虽然字符串是Redis的基本值类型,但你仍然能通过它完成一些有趣的操作。例如:原子递增:

    127.0.0.1:6379> set numm 1 OK 127.0.0.1:6379> incr numm (integer) 2

    注意:递增的值只能是整型的,如果是字符型的,则会报错。如下

    127.0.0.1:6379> incr onekey (error) ERR value is not an integer or out of range

    INCR 命令将字符串值解析成整型,将其加一,最后将结果保存为新的字符串值,类似的命令有INCRBY, DECR 和 DECRBY。

    INCRBY 命令

    将key对应的数字加decrement。如果key不存在,操作之前,key就会被置为0。如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。

    返回值

    integer-reply: 增加之后的value值。

    例子

    redis> SET mykey "10" OK redis> INCRBY mykey 5 (integer) 15 redis>

    DECR和DECRBY表示减法,用法和INCR和INCRBY 是一样的,只不过表示的是减法

    注:以上的增减命令,如果key不存在,那么在操作之前,这个key对应的值会被置为0,所以不用担心key不存在的问题

    INCR是原子性操作的,就是说即使多个客户端对同一个key发出INCR命令,也决不会导致竞争的情况。例如如下情况永远不可能发生:『客户端1和客户端2同时读出“10”,他们俩都对其加到11,然后将新值设置为11』。最终的值一定是12,read-increment-set操作完成时,其他客户端不会在同一时间执行任何命令。

    获取或存储多个值

    我们如果想一次存储或获取多个key对应的值,可以使用MSET和MGET命令:

    127.0.0.1:6379> mset a 1 b 2 OK 127.0.0.1:6379> mget a b

    “1”“2”

    MGET 命令返回由值组成的数组。

    GETSET命令

    语法 GETSET key value

    将key的值设置成value值并且返回原来key对应的value(旧值)。如果key存在但是对应的value不是字符串,就返回错误。

    修改或查询键空间

    有些指令不是针对任何具体的类型定义的,而是用于和整个键空间交互的。因此,它们可被用于任何类型的键。

    使用EXISTS命令返回1或0标识给定key的值是否存在,使用DEL命令可以删除key对应的值,DEL命令返回1或0标识值是被删除(值存在)或者没被删除(key对应的值不存在)。

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

    TYPE命令可以返回key对应的值的存储类型:

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

    设置过期时间:

    我们可以对key设置一个超时时间,当这个时间到达后该key会被删除。

    一、使用expire设置过期时间(也可以再次调用这个命令来改变超时时间,使用PERSIST命令去除超时时间 )适用于key已经存在的情况,时间单位为秒

    expire key 5

    二、我们也可以在创建值的时候设置超时时间,ex表示秒,px表示毫秒

    127.0.0.1:6379> set k 100 ex 10 OK 127.0.0.1:6379> get k "100" 127.0.0.1:6379> get k (nil)

    TTL命令用来查看key对应的值剩余存活时间。例:ttl key

    Redis Lists

    一般意义上讲,列表就是有序元素的序列:10,20,1,2,3就是一个列表。但用数组实现的List和用Linked List实现的List,在属性方面大不相同。

    Redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素,在头部或尾部添加一个元素的操作,其时间复杂度也是常数级别的。用LPUSH 命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。

    那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在linked list实现的list上没有那么快。

    Redis Lists用linked list实现的原因是:因为对于数据库系统来说,至关重要的特性是:能非常快的在很大的列表上添加元素。另一个重要因素是,正如你将要看到的:Redis lists能在常数时间取得常数长度。

    如果快速访问集合元素很重要,建议使用可排序集合(sorted sets)。

    Redis lists 入门

    LPUSH 命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE 命令可从list中取出一定范围的元素:

    127.0.0.1:6379> LPUSH mylist 1 (integer) 1 127.0.0.1:6379> LPUSH mylist 2 (integer) 2 127.0.0.1:6379> RPUSH mylist 3 (integer) 3 127.0.0.1:6379> LRANGE mylist 0 -1 1) "2" 2) "1" 3) "3"

    注意:LRANGE 带有两个索引,一定范围的第一个和最后一个元素。这两个索引都可以为负来告知Redis从尾部开始计数,因此-1表示最后一个元素,-2表示list中的倒数第二个元素,以此类推。

    当然,我们使用lpush和rpush的时候,可以传入多个值

    删除list的元素使用lpop或者rpop,lpop为在list的左边(头部)删除一个元素,rpop为在list的右边(尾部)删除一个元素

    LTRIM把list从左边截取指定长度。

    修剪(trim)一个已存在的 list,这样 list 就会只包含指定范围的指定元素。start 和 stop 都是由0开始计数的, 这里的 0 是列表里的第一个元素(表头),1 是第二个元素,以此类推。start 和 end 也可以用负数来表示与表尾的偏移量,比如 -1 表示列表里的最后一个元素, -2 表示倒数第二个,等等。

    List的常用案例

    正如你可以从上面的例子中猜到的,list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是,你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作,将会非常快,也会很容易扩展到百万级别元素的规模。

    例如在评级系统中,比如社会化新闻网站 reddit.com,你可以把每个新提交的链接添加到一个list,用LRANGE可简单的对结果分页。

    在博客引擎实现中,你可为每篇日志设置一个list,在该list中推入博客评论,等等。

    List上的阻塞操作

    可以使用Redis来实现生产者和消费者模型,如使用LPUSH和RPOP来实现该功能。但会遇到这种情景:list是空,这时候消费者就需要轮询来获取数据,这样就会增加redis的访问压力、增加消费端的cpu时间,而很多访问都是无用的。为此redis提供了阻塞式访问 BRPOP 和 BLPOP 命令。 消费者可以在获取数据时指定如果数据不存在阻塞的时间,如果在时限内获得数据则立即返回,如果超时还没有数据则返回null, 0表示一直阻塞。

    同时redis还会为所有阻塞的消费者以先后顺序排队。

    BRPOP 命令

    语法

    BRPOP key [key …] timeout

    返回值

    当没有元素可以被弹出时返回一个 nil 的多批量值,并且 timeout 过期。

    当有元素弹出时会返回一个双元素的多批量值,其中第一个元素是弹出元素的 key,第二个元素是 value。

    例:

    127.0.0.1:6379> BRPOP mylist 2

    “mylist”“3”

    key 的自动创建和删除

    目前为止,在我们的例子中,我们没有在推入元素之前创建空的 list,或者在 list 没有元素时删除它。在 list 为空时删除 key,并在用户试图添加元素(比如通过 LPUSH)而键不存在时创建空 list,是 Redis 的职责。

    这不光适用于 lists,还适用于所有包括多个元素的 Redis 数据类型 – Sets, Sorted Sets 和 Hashes。

    基本上,我们可以用三条规则来概括它的行为:

    1、当我们向一个聚合数据类型中添加元素时,如果目标键不存在,就在添加元素前创建空的聚合数据类型。

    2、当我们从聚合数据类型中移除元素时,如果值仍然是空的,键自动被销毁。(即所有的元素被弹出之后, key 不复存在。)

    3、对一个空的 key 调用一个只读的命令,比如 LLEN (返回 list 的长度),或者一个删除元素的命令,将总是产生同样的结果。该结果和对一个空的聚合类型做同个操作的结果是一样的。

    Redis哈希

    Redis Hashes是字符串字段和字符串值之间的映射,所以它们是完美的表示对象的数据类型。

    一个拥有少量字段的hash只需要 很少的空间来存储,所有你可以在一个小型的 Redis实例中存储上百万的对象。

    Redis哈希使用字段-值对的方式,看起来与人们期望的“散列”看起来完全一样:

    127.0.0.1:6379> HMSET user name m age 18 OK 127.0.0.1:6379> HGET user name "m"

    HMSET 语法

    HMSET key field1 value1 field2 value2...

    Hash 便于表示 objects,实际上,你可以放入一个 hash 的域数量实际上没有限制(除了可用内存以外)。

    HMSET命令设置哈希的多个字段,HSET设置哈希的一个字段,而HGET检索单个字段。HMGET检索多个字段,返回一个数组。

    hash的命令跟普通string命令差不多,只是前面多了个h

    下面介绍一些常用的hash命令

    //删除某个key的field

    HDEL key field [field ...]

    //返回哈希的所有键值对

    HGETALL key

    //返回哈希中包含的字段数

    HLEN key

    //设置哈希中field 的值,只有当field不存在才能成功

    HSETNX key field value

    //返回哈希中的所有值

    HVALS key

    值得注意的是,小哈希(即,一些具有较小值的元素)以特殊方式在内存中进行编码,从而使它们具有很高的内存效率。

    Redis Sets

    Redis Sets是一个无序的字符串合集。你可以以O(1) 的时间复杂度(无论集合中有多少元素时间复杂度都为常量)完成 添加,删除以及测试元素是否存在的操作。

    Redis Sets有着不允许相同成员存在的优秀特性。向集合中多次添加同一元素,在集合中最终只会存在一个此元素。实际上这就意味着,在添加元素前,你并不需要事先进行检验此元素是否已经存在的操作。

    Redis Sets集是字符串的无序集合。SADD 指令把新的元素添加到 set 中,对 set 也可做一些其他的操作,比如测试一个给定的元素是否存在,对不同 set 取交集,并集或差,等等

    下面介绍下sets的常用命令

    //往set添加元素

    SADD key member [member ...]

    //返回set集合中的所有元素

    SMEMBERS key

    //删除并返回删除的元素,可以指定删除的个数,如果未指定个数,默认为1个

    SPOP key [count]

    //返回set集合的元素个数,为0则表示集合为空

    SCARD key

    //返回由第一个集合和所有连续集合之间的差得出的集合成员(即第一个集合中其他集合没有的元素)。

    SDIFF key [key ...]

    例:

    key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SDIFF key1 key2 key3 = {b,d}

    //判断该member元素是否是存储在集合的成员

    SISMEMBER key member

    //将source集合的member元素移动到destination集合。如果源集不存在或不包含指定的元素,则不执行任何操作并0返回。否则,该元素将从源集中删除,并添加到目标集中。如果指定的元素已存在于目标集中,则仅将其从源集中删除。

    SMOVE source destination member

    //从指定的集合中删除指定的成员member ,不是该集合成员的指定成员将被忽略。如果key不存在,则将其视为空集,并且此命令返回 0。

    SREM key member [member ...]

    //返回所有给定集合的并集产生的集合成员。

    SUNION key [key ...] 例: key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SUNION key1 key2 key3 = {a,b,c,d,e}

    SUNIONSTORE 用于对多个集合取并集,并把结果存入另一个 set(即destination ) 中

    SUNIONSTORE destination key [key ...]

    //随机返回count个元素,不指定count,则为返回一个

    SRANDMEMBER key [count]

    //sinter 第一个集合与后续集合做比较,并返回第一个集合的交集

    SINTER key [key ...]

    例:

    key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SINTER key1 key2 key3 = {c}

    //将集合的交集放到destination 集合中

    SINTERSTORE destination key [key ...]

    有序集合(Sorted sets)

    Redis有序集合和Redis集合类似,也称ZSET,是不包含 相同字符串的合集。它们的差别是,每个有序集合 的成员都关联着一个评分,这个评分用于把有序集 合中的成员按最低分到最高分排列。

    使用有序集合,你可以非常快地(O(log(N)))完成添加,删除和更新元素的操作。 因为元素是在插入时就排好序的,所以很快地通过评分(score)或者 位次(position)获得一个范围的元素。 访问有序集合的中间元素同样也是非常快的,因此你可以使用有序集合作为一个没用重复成员的列表。 在这个列表中, 你可以轻易地访问任何你需要的东西: 有序的元素,快速的存在性测试,快速访问集合中间元素!

    有序集合按照以下规则排序:

    1、如果A和B是两个具有不同分数的元素,则如果A.score是> B.score,则A>B。

    2、如果A和B的得分完全相同,那么如果A字符串在字典上大于B字符串,则A>B。A和B字符串不能相等,因为排序集仅具有唯一元素。

    下面是有序集合的常用命令:

    ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

    例:

    127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" (integer) 2

    将所有指定成员添加到键为key有序集合(sorted set)里面。 添加时可以指定多个分数/成员(score/member)对。 如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置。

    如果key不存在,将会创建一个新的有序集合(sorted set)并将分数/成员(score/member)对添加到有序集合,就像原来存在一个空的有序集合一样。如果key存在,但是类型不是有序集合,将会返回一个错误应答。

    分数值是一个双精度的浮点型数字字符串。+inf和-inf都是有效值。

    ZADD 命令在key后面的分数/成员对(score/member)前面支持添加一些参数,他们是:

    XX: 仅仅更新存在的成员,不添加新成员。

    NX: 不更新存在的成员。只添加新成员。

    CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内。注:在通常情况下,ZADD返回值只计算新添加成员的数量。

    INCR: 当ZADD指定这个选项时,成员的操作就等同ZINCRBY命令,对成员的分数进行递增操作。

    ZCARD key

    返回key的有序集元素个数,不存在返回0。

    ZCOUNT key min max

    返回指定分数范围的元素个数。

    例:

    127.0.0.1:6379> ZCOUNT myzset 1 2 (integer) 2 ZINCRBY key increment member

    为有序集key的成员member的score值加上增量increment。如果key中不存在member,就在key中添加一个member,score是increment(就好像它之前的score是0.0)。如果key不存在,就创建一个只含有指定member成员的有序集合。

    ZLEXCOUNT key min max

    计算有序集合中指定成员之间的成员数量。

    完整示例

    zlexcount zset [member1 [member5 指令 是否必须 说明 zlexcount 是 指令 key 是 有序集合键名称 min 是 在有序集合中分数排名较小的成员 max 是 在有序集合中分数排名较大的成员

    提示: 成员名称前需要加 [ 符号作为开头, [ 符号与成员之间不能有空格

    可以使用 - 和 + 表示得分最小值和最大值

    min 和 max 不能反, max 放前面 min放后面会导致返回结果为0

    计算成员之间的成员数量时,参数 min 和 max 的位置也计算在内。

    ZRANK key member

    返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。

    ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

    返回有序集合中指定分数区间内的成员,分数由高到低排序。

    ZREMRANGEBYSCORE key min max

    移除有序集key中,所有score值介于min和max之间(包括等于min或max)的成员。 自版本2.1.6开始,score值等于min或max的成员也可以不包括在内。增加(符号可以不包括min或max值。

    例:

    ZREMRANGEBYSCORE myzset (1 (10

    Zrevrange 命令

    返回有序集中,指定区间内的成员。其中成员的位置按分数值递减(从大到小)来排列。

    语法:

    redis 127.0.0.1:6379> ZREVRANGE key start stop [WITHSCORES]

    例:

    ZREVRANGE salary 0 -1 WITHSCORES

    Zrange 命令

    返回有序集中,指定区间内的成员。其中成员的位置按分数值递增(从小到大)来排序。

    其中成员的位置按分数值递增(从小到大)来排序。

    语法:

    ZRANGE key start stop [WITHSCORES]

    例:

    ZRANGE salary 0 -1 WITHSCORES
    Processed: 0.017, SQL: 9