Redis学习——数据结构下

4、集合(集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。)

1、命令

.集合内操作

1、添加元素 sadd key element [element ...]返回结果为添加成功的元素个数。

2、删除元素 srem key element [element ...]返回结果为成功删除元素个数。

3、计算元素个数 scard key

(scard的时间复杂度为O(1),它不会遍历集合所有元素,而是直接用Redis内部的变量)

4、判断元素是否在集合中 sismember key element 如果给定元素element在集合内返回1,反之返回0

5、随机从集合返回指定个数元素 srandmember key [count] [count]是可选参数,如果不写默认为1

6、从集合随机弹出元素 spop key (spop操作可以从集合中随机弹出一个元素,Redis从3.2版本开始,spop也支持[count]参数)

7、获取所有元素 smembers key

(smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan来完成)

.集合间操作

1、求多个集合的交集 sinter key [key ...]

2、求多个集合的并集 suinon key [key ...]

3、求多个集合的差集 sdiff key [key ...]

4、将交集、并集、差集的结果保存 sinterstore destination key [key ...]

suionstore destination key [key ...]

sdiffstore destination key [key ...]

   (集合间的运算在元素较多的情况下会比较耗时,所以Redis提供了上面三个命令(原命令+store)将集合间交集、并集、差集的结果保存在

destination key中,例如下面操作将user:1:follow和user:2:follow两个集合的交集结果保存在user:1_2:inter中,user:1_2:inter本身也是集合类

sinterstore user:1_2:inter user:1:follow user:2:follow

    )

2、内部编码

·intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。

·hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

3、使用场景(集合类型比较典型的使用场景是标签(tag)。)

(例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣

                         点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共

                         同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。例如一

                         个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品

                         比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产

                         品,通常会为网站带来更多的利益)

集合类型的应用场景通常为以下几种

·sadd=Tagging(标签)

·spop/srandmember=Random item(生成随机数,比如抽奖)

·sadd+sinter=Social Graph(社交需求)

5、有序集合

( 有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。有序集合中的元素不能重复,但是score可以重复,就和一个班里的同学学号不能重复,但是考试成绩可以相同。)

1、命令

·集合内

1、添加成员 zadd key score member [score member ...] 返回结果代表成功添加成员的个数。

·Redis3.2为zadd命令添加了nx、xx、ch、incr四个选项:

·nx:member必须不存在,才可以设置成功,用于添加。

·xx:member必须存在,才可以设置成功,用于更新。

·ch:返回此次操作后,有序集合元素和分数发生变化的个数

·incr:对score做增加,相当于后面介绍的zincrby。

·有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间

复杂度为O(log(n)),sadd的时间复杂度为O(1)。

2、计算成员个数 zcard key

3、计算某个成员的分数 zscore key member

4、计算成员的排名

zrank key member 是从分数从低到高返回排名,zrevrank反之

5、删除成员 zrem key member [member ...] 返回结果为成功删除的个数。

6、增加成员的分数 zincrby key increment member

zincrby user:ranking 9 tom(tom增加了9分)

7、返回指定排名范围的成员

zrange key start end [withscores]

zrevrange key start end [withscores]

(有序集合是按照分值排名的,zrange是从低到高返回,zrevrange反之。)

8、返回指定分数范围的成员

其中zrangebyscore按照分数从低到高返回,zrevrangebyscore反之

9、返回指定分数范围成员个数

zcount key min max

zcount user:ranking 200 221 :返回200到221分的成员的个数

10、删除指定排名内的升序元素 

zremrangebyrank key start end :删除第start到第end名的成员

11、删除指定分数范围的成员  zremrangebyscore key min max

zremrangebyscore user:ranking (250 +inf :将250分以上的成员全部删除

·集合间的操作

1、交集 zinterstore destination numkeys key [key ...] [weights weight [weight ...]][aggregate sum|min|max]

这个命令参数较多,下面分别进行说明:

·destination:交集计算结果保存到这个键。

·numkeys:需要做交集计算键的个数。

·key[key...]:需要做交集计算的键。

·weights weight[weight...]:每个键的权重,在做交集计算时,每个键中

的每个member会将自己分数乘以这个权重,每个键的权重默认是1。

·aggregate sum|min|max:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。

2、并集 zunionstore destination numkeys key [key ...] [weights weight [weight ...]][aggregate sum|min|max]

(该命令的所有参数和zinterstore是一致的,只不过是做并集计算)

2、内部编码

·ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配

置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。

·skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。

3、使用场景

有序集合比较典型的使用场景就是排行榜系统。例如视频网站需要对用

户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播

放数量、按照获得的赞数。本节使用赞数这个维度,记录每天用户上传视频

的排行榜。

6、键管理

1、单个键管理

针对单个键的命令,前面几节已经介绍过一部分了,例如type、del、object、exists、expire等,下面将介绍剩余的几个重要命令。

1、键重命名 rename key newkey (如果newKey已经存在,值也会被覆盖)

(为了防止被强行rename,Redis提供了renamenx命令,确保只有newKey

不存在时候才被覆盖,例如下面操作renamenx时,newkey=python已经存在,

返回结果是0代表没有完成重命名,所以键java和python的值没变)

  在使用重命名命令时,有两点需要注意:

·由于重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性,这点不要忽视。

·如果rename和renamenx中的key和newkey如果是相同的,在Redis3.2和之前版本返回结果略有不同。

2、随机返回一个键 randomkey

3、键过期

除了expire、ttl命令以外,Redis还提供了expireat、pexpire、pexpireat、pttl、persist等一系列命令,下面分别进行说明:

·expire key seconds:键在seconds秒后过期。

·expireat key timestamp:键在秒级时间戳timestamp后过期。

ttl命令和pttl都可以查询键的剩余过期时间,但是pttl精度更高可以达到毫秒级别,有3种返回值:

·大于等于0的整数:键剩余的过期时间(ttl是秒,pttl是毫秒)。

·-1:键没有设置过期时间。

·-2:键不存在。

·pexpire key milliseconds:键在milliseconds毫秒后过期。

·pexpireat key milliseconds-timestamp键在毫秒级时间戳timestamp后过期。

在使用Redis相关过期命令时,需要注意以下几点。

1)如果expire key的键不存在,返回结果为0

2)如果过期时间为负值,键会立即被删除,犹如使用del命令一样

3)persist命令可以将键的过期时间清除

4)对于字符串类型键,执行set命令会去掉过期时间,这个问题很容易在开发中被忽视。

5)Redis不支持二级数据结构(例如哈希、列表)内部元素的过期功能,例如不能对列表类型的一个元素做过期时间设置。

6)setex命令作为set+expire的组合,不但是原子执行,同时减少了一次网络通讯的时间

4、迁移键

迁移键功能非常重要,因为有时候我们只想把部分数据由一个Redis迁移到另一个Redis(例如从生产环境迁移到测试环境),Redis发展历程中提

供了move、dump+restore、migrate三组迁移键的方法,它们的实现方式以及使用的场景不太相同,下面分别介绍

(1)move: move key db

move命令用于在Redis内部进行数据迁移,Redis内部可以有多个数据库,彼此在数据上是相互隔离的,move key db就

是把指定的键从源数据库移动到目标数据库中,多数据库功能不建议在生产环境使用,所以这个命令读者知道即可。

(2)dump+restore

dump key

restore key ttl value

dump+restore可以实现在不同的Redis实例之间进行数据迁移的功能,整个迁移的过程分为两步:

1)在源Redis上,dump命令会将键值序列化,格式采用的是RDB格式。

2)在目标Redis上,restore命令将上面序列化的值进行复原,其中ttl参数代表过期时间,如果ttl=0代表没有过期时间。

有关dump+restore有两点需要注意:

第一,整个迁移过程并非原子性的,而是通过客户端分步完成的。

第二,迁移过程是开启了两个客户端连接,所以dump的结果不是在源Redis和目标Redis之间进行传输

(3)migrate

migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key

migrate命令也是用于在Redis实例间进行数据迁移的,实际上migrate命令就是将dump、restore、del三个命令进行组合,从而简化了操作流程。

migrate命令具有原子性,而且从Redis3.0.6版本以后已经支持迁移多个键的

功能,有效地提高了迁移效率,migrate在10.4节水平扩容中起到重要作用。

2、遍历键(Redis提供了两个命令遍历所有的键,分别是keys和scan)

1.全量遍历键 keys pattern (pattern使用的是glob风格的通配符)

·*代表匹配任意字符。

·代表匹配一个字符。

·[]代表匹配部分字符,例如[1,3]代表匹配1,3,[1-10]代表匹配1到10的任意数字。

·x用来做转义,例如要匹配星号、问号需要进行转义

   如果Redis包含了大量的键,执行keys命令很可能会造成Redis阻塞,所以一般建议不要在生

   产环境下使用keys命令。但有时候确实有遍历键的需求该怎么办,可以在以下三种情况使用:

·在一个不对外提供服务的Redis从节点上执行,这样不会阻塞到客户端的请求,但是会影响到主从复制。

·如果确认键值总数确实比较少,可以执行该命令。

·使用下面要介绍的scan命令渐进式的遍历所有键,可以有效防止阻塞。

2.渐进式遍历:scan cursor [match pattern] [count number]

Redis从2.8版本后,提供了一个新的命令scan,它能有效的解决keys命令存在的问题。和keys命令执行时会遍历所有键不同,scan采用渐进式遍历

的方式来解决keys命令可能带来的阻塞问题,每次scan命令的时间复杂度是O(1),但是要真正实现keys的功能,需要执行多次scan。

scan cursor [match pattern] [count number]各参数含义:

·cursor是必需参数,实际上cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值,直到游标值为0,表示遍历结束。

·match pattern是可选参数,它的作用的是做模式的匹配,这点和keys的模式匹配很像。

·count number是可选参数,它的作用是表明每次要遍历的键个数,默认值是10,此参数可以适当增大。

  除了scan以外,Redis提供了面向哈希类型、集合类型、有序集合的扫

  描遍历命令,解决诸如hgetall、smembers、zrange可能产生的阻塞问题,对

  应的命令分别是hscan、sscan、zscan,它们的用法和scan基本类似。

  )

  **渐进式遍历可以有效的解决keys命令可能产生的阻塞问题,但是scan并

    非完美无瑕,如果在scan的过程中如果有键的变化(增加、删除、修改),

    那么遍历效果可能会碰到如下问题:新增的键可能没有遍历到,遍历出了重

    复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键,这些是我们在开发时需要考虑的。

7、数据库管理(Redis提供了几个面向Redis数据库的操作,它们分别是dbsize、select、flushdb/flushall命令)

1.切换数据库(Redis是用数字作为多个数据库的实现。Redis默认配置中是有16个数据库)

select dbIndex

2.flushdb/flushall

flushdb/flushall命令用于清除数据库,两者的区别的是flushdb只清除当前数据库,flushall会清除所有数据库。

flushdb/flushall命令可以非常方便的清理数据,但是也带来两个问题:

·flushdb/flushall命令会将所有数据清除,一旦误操作后果不堪设想。

·如果当前数据库键值数量比较多,flushdb/flushall存在阻塞Redis的可能性。

参考资料:《Redis开发与运维》

原文地址:https://www.cnblogs.com/jnba/p/10811916.html