Redis重要知识点总结一(基于键值的数据结构服务器)

Redis重要总结

它提供了五种数据结构:
字符串、哈希、列表、集合、有序集合,一个数据结构内部有几种编码方式。

一、特性

  • 数据放在内存中
  • C语言实现的
  • 单线程架构,预防了多线程可能产生的竞争问题

二、全局命令

Redis有5种数据结构,他们是键值对中的值,对于键来说有一些通用的命令。
    1、查看所有键
        keys *
    2、键总数
        dbsize
    注意:
        dbsize命令在计算键总数时不会遍历所有键,而是直接获取Redis内置的键总数变量,所以dbsize命令的时间复杂度是O(1)。而keys命令会遍历所有键,所以它的时间复杂度是O(n),当Redis保存了大量键时,线上环境禁止使用。
    3、检查键是否存在
        exists key:如果键存在则返回1,不存在则返回0
    4、删除键
        del key [key ...]
        返回结果为成功删除键的个数,假设删除一个不存在的键,就会返回0.
        del是一个通用命令,无论值是什么数据结构类型,del命令都可以将其删除。
    5、键过期expire	英[ɪkˈspaɪə(r)]终止

        expire key seconds
        
        expire:失效,终止
        Redis支持对键添加过期时间,当超过过期时间后,会自动删除键,例如为键hello设置了10秒过期时间
        expire hello 10
        
        
    6、ttl命令会返回键的剩余过期时间,它有3种返回值: 
        1、大于等于0的整数:键剩余的过期时间
        2-1:键没设置过期时间
        3-2:键不存在
        
        ttl hello
    7、键的数据结构类型
        type key
        例如键hello是字符串类型,返回结果为string。键mylist是列表类型,返回结果为list,如果键不存在,返回null.

三、String(字符串)

常用命令

1、设置值
    set key value [ex seconds] [px milliseconds] [nx|xx] 
    set命令有几个选项: 
    1、ex seconds:为键设置秒级过期时间。 
    2、px milliseconds:为键设置毫秒级过期时间。 
    3、nx:键必须不存在,才可以设置成功,用于添加。 
    4、xx:与nx相反,键必须存在,才可以设置成功,用于更新。
    
    除了set选项,Redis还提供了setex和setnx两个命令:
    它们的作用和ex和nx选项是一样的。下面的例子说明了set、setnx、set xx的区别。
    
    SETNX key value
        只有在 key 不存在时设置 key 的值。
    SETEX key seconds value
        将值 value 关联到 key ,并将 key 的过期时间设为 seconds 、(以秒为单位)。
    
    setnx和setxx在实际使用中有什么应用场景吗?以setnx命令为例子,由于Redis的单线程命令处理机制,如果有多个客户端同时执
    行setnx key value,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种 实现方案。

2、获取值
    get key
    如果要获取的键不存在,则返回nil(空)
3、批量设置值
    mset key value [key value ...]
4、批量获取值
    mget key [key ...] 
    mget a b c d
    如果有些键不存在,那么它的值为nil(空),结果是按照传入键的顺序返回
    
    说明:批量操作命令可以有效提高开发效率。
    假如没有mget这样的命令,,要执行n次get命令,具体耗时如下:
        n次get时间 = n次网络时间 + n次命令时间
    使用mget命令后,具体耗时如下:
        n次get时间 = 1次网络时间 + n次命令时间
5、计数
    incr key
    incr命令用于对值做自增操作,返回结果分为三种情况: 
    1、值不是整数,返回错误。 2、值是整数,返回自增后的结果。 3、键不存在,按照值为0自增,返回结果为1

除了incr命令,Redis提供了decr(自减)、incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数):
    decr key 
    incrby key increment 
    decrby key decrement 
    incrbyfloat key increment

计数:incr key
incr命令用于对值做自增操作,返回结果分为三种情况:

  • 1、值不是整数,返回错误。
  • 2、值是整数,返回自增后的结果。
  • 3、键不存在,按照值为0自增,返回结果为1

SETEX key seconds value
将值 value 关联到 key ,并将 key 的过期时间设为 seconds 、(以秒为单位)。

应用场景(缓存、计数、限速)

  • 1、缓存
  • 2、计数
  • 3、限速
    很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制
    用户每分钟获取验证码的频率。
phoneNum = "138xxxxxxxx"; 
key = "shortMsg:limit:" + phoneNum; 
// SET key value EX 60 NX 
isExists = redis.set(key,1,"EX 60","NX"); 
if(isExists != null || redis.incr(key) <=5)
{ 
    // 通过
}
else
{ 
    // 限速
}

四、哈希(用于保存对象,每个对象只用一个键保存)

1、命令

1、设置值
    hset key field value
    下面为user:1添加一对field-value:
        hset user:1 name tom
    如果设置成功会返回1,反之会返回02、获取值
    hget key field
3、删除field
    hdel key field [field ...]
    hdel会删除一个或多个field,返回结果为成功删除field的个数
4、计算field个数
    hlen key
5、批量设置或获取field-value
    hmget key field [field ...] 
    hmset key field value [field value ...]
6、判断field是否存在 hexists
    hexists key field
7、获取所有field
    hkeys key
8、获取所有value
    hvals key
9、获取所有的field-value
    hgetall key
10、hincrby hincrbyfloat
11、计算value的字符串长度
    hstrlen key field

2、应用场景(缓存用户信息)

可用于缓存用户信息
每个用户属性使用一对field-value,但是只用一个键保存。
hmset user:1 name tom age 23 city beijing

五、列表list(一个键,装的不是一个数字)

在redis中,可以对列表两端进行插入和弹出操作,也有阻塞操作,还可以获得指定范围的元素列表,获取指定索引下表的元素等。
它可以充当栈和队列的角色,在实际开发上有很多应用场景。

命令

1、添加
    从右边插入元素
        rpush
    从左边插入元素
        lpush key value [value ...]
    向某个元素前或者后插入元素
        linsert key before|after pivot value
        linsert命令会从列表中找到等于pivot的元素,在其前(before)或者后(after)插入一个新的元素value。

2、查找
    获取指定范围内的元素列表
        lrange key start end
        索引下表有两个特点
        第一,索引下标从左到右分别是0到N-1,但是从右到左分别是-1-N。 
        第二,lrange中的end选项包含了自身,这个和很多编程语言不包含end不太 相同,例如想获取列表的第2到第4个元素
    
    获取列表指定索引下标的元素
        lindex key index
    
    获取列表的长度
        llen key
        
3、删除
    从列表左侧弹出元素
        lpop key
    从列表右侧弹出
        rpop key
    删除指定元素
        lrem key count value

    lrem命令会从列表中找到等于value的元素进行删除,根据count的不同
    分为三种情况: 
        1、count>0,从左到右,删除最多count个元素。 
        2、count<0,从右到左,删除最多count绝对值个元素。
        3、count=0,删除所有。
    
    按照索引范围修剪列表
        ltrim key start end
4、修改
    修改指定索引下标的元素:
        lset key index newValue

5、阻塞操作
    blpop key [key ...] timeout 
    brpop key [key ...] timeout

    blpop和brpop是lpop和rpop的阻塞版本,它们除了弹出方向不同,使用方法基本相同,所以下面以brpop命令进行说明,brpop命令包含两个参数:
        1、key[key...]:多个列表的键。 
        2、timeout:阻塞时间(单位:秒)。
    
    列表不为空:客户端会立即返回。
    列表为空:
        如果timeout=3,那么客户端要等到3秒后返回,如果timeout=0,那么客户端一直阻塞等下去:
    如果阻塞添加了数据element1,客户端立即返回。
    
    注意点:
        1、第一点,如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立即返回。
        2、第二点,如果多个客户端对同一个键执行brpop,那么最先执行brpop命令的客户端可以获取到弹出的值。

应用场景(消息队列(使用阻塞))

消息队列
如图2-21所示,Redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端使用lrpush从列表左侧插入元素,多个消费者客户端
使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用 性。

列表选择口诀

  • 1、lpush+lpop=Stack(栈)
  • 2、lpush+rpop=Queue(队列)
  • 3、lpsh+ltrim=Capped Collection(有限集合)
  • 4、lpush+brpop=Message Queue(消息队列)

六、集合Set

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

Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题。

命令

集合内操作
1、添加元素 
    sadd key element [element ...]
2、删除元素
    srem key element [element ...]
3、计算元素个数
    scard key
    scard的时间复杂度为O(1),它不会遍历集合所有元素,而是直接用 Redis内部的变量
4、判断元素是否在集合中 
    sismember key element
5、随机从集合返回指定个数元素
    srandmember key [count]
6、从集合随机弹出元素
    spop key
    srandmember和spop都是随机从集合选出元素,两者不同的是spop命令执行后,元素会从集合中删除,而srandmember不会。
7、获取所有元素
    smembers key
集合间操作
1、求多个集合的交集
    sinter key [key ...] 
    例如下面代码是求user:1:follow和user:2:follow两个集合的交集:
        sinter user:1:follow user:2:follow
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中,destination还是set。

使用场景(给用户添加标签(不可以重复))

集合类型比较典型的使用场景是标签(tag)。例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣 点就是标签。
1、给用户添加标签
    sadd user:1:tags tag1 tag2 tag5
    sadd user:2:tags tag2 tag3 tag5
2、给标签添加用户
    sadd tag1:users user:1 user:3 
    sadd tag2:users user:1 user:2 user:3

七、有序集合(按分数score)

集合内

1、添加元素
    zadd key score member [score member ...]
·Redis3.2为zadd命令添加了nx、xx、ch、incr四个选项:
    1、nx:member必须不存在,才可以设置成功,用于添加。 
    2、xx:member必须存在,才可以设置成功,用于更新。 
    3、ch:返回此次操作后,有序集合元素和分数发生变化的个数 
    4、incr:对score做增加,相当于后面介绍的zincrby。
2、计算成员个数
    zcard key
3、计算某个成员的分数
    zscore key member
4、计算成员的排名
    zrank key member 
    zrevrank key member
    zrank是从分数从低到高返回排名,zrevrank反之。(排名从0开始计算)
5、删除成员
    zrem key member [member ...]
6、增加成员的分数
    zincrby key increment member
    下面操作给tom增加了9分,分数变为了260分:
        zincrby user:ranking 9 tom
7、返回指定排名范围的成员
    zrange key start end [withscores] 
    zrevrange key start end [withscores]
8、返回指定分数范围的成员
    zrangebyscore key min max [withscores] [limit offset count] 
    zrevrangebyscore key max min [withscores] [limit offset count]
9、返回指定分数范围成员个数
    zcount key min max
10、删除指定排名内的升序元素
    zremrangebyrank key start end
11、删除指定分数范围的成员
    zremrangebyscore key min max

集合间操作

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是一致的,只不过是做并集计算

应用场景(排行榜)

有序集合比较典型的使用场景就是排行榜系统。例如视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播
放数量、按照获得的赞数。本节使用赞数这个维度,记录每天用户上传视频 的排行榜。

展示获取赞数最多的十个用户
zrevrangebyrank user:ranking:2016_03_15 0 9

八、键管理

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

1.键重命名
    rename key newkey
    为了防止被强行rename,Redis提供了renamenx命令,确保只有newKey不存在时候才被覆盖
2.随机返回一个键
    randomkey
3.键过期
    expire:终止,失效
    ·expire key seconds:键在seconds秒后过期。 
    ·expireat key timestamp:键在秒级时间戳timestamp后过期。

    Redis2.6版本后提供了毫秒级的过期方案: ·pexpire key milliseconds:键在milliseconds毫秒后过期。
    ·pexpireat key milliseconds-timestamp键在毫秒级时间戳timestamp后过期。

ttl命令和pttl都可以查询键的剩余过期时间,但是pttl精度更高可以达到毫秒级别,有3种返回值: 
	·大于等于0的整数:键剩余的过期时间(ttl是秒,pttl是毫秒)。 
	·-1:键没有设置过期时间。 
	·-2:键不存在。
    
    persist命令可以将键的过期时间清除
    Persist:持续存在
    persist key

1、迁移键(move、dump+restore(dump使用RDB)、migrate)

migrate 英[maɪˈɡreɪt] 迁移
迁移键功能非常重要,因为有时候我们只想把部分数据由一个Redis迁移到另一个Redis(例如从生产环境迁移到测试环境),Redis发展历程中提供了move、dump+restore、migrate三组迁移键的方法,它们的实现方式以及使用的场景不太相同,下面分别介绍:

  • 1、move
    move key db
    move命令用于在Redis内部进行数据迁移,Redis内部可以有多个数据库,由于多个数据库功能后面会进行介绍,这里只需要知道Redis内部可以有多个数据库,彼此在数据上是相互隔离的,move key db就是把指定的键从源数据库移动到目标数据库中,但笔者认为多数据库功能不建议在生产环境使用,所以这个命令读者知道即可。

  • 2、dump+restore
    dump+restore可以实现在不同的Redis实例之间进行数据迁移的功能,整个迁移的过程分为两步:
    1)在源Redis上,dump命令会将键值序列化,格式采用的是RDB格式。
    2)在目标Redis上,restore命令将上面序列化的值进行复原,其中ttl参数代表过期时间,如果ttl=0代表没有过期时间。
    有关dump+restore有两点需要注意:
    第一,整个迁移过程并非原子性的,而是通过客户端分步完成的。
    第二,迁移过程是开启了两个客户端连接,所以dump的结果不是在源Redis和目标Redis之间进行传输,下面用一个 例子演示完整过程。
    例子:
    1、在源Redis上执行dump:
    redis-source> set hello world OK
    2、在目标Redis上执行restore:
    redis-target> restore hello 0 “\x00\x05world\x06\x00\x8f<T\x04%\xfcNQ”
    在这里插入图片描述

  • 3、migrate
    migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key …]]

    下面对migrate的参数进行逐个说明:
    ·host:目标Redis的IP地址。
    ·port:目标Redis的端口。
    ·key|"":在Redis3.0.6版本之前,migrate只支持迁移一个键,所以此处是要迁移的键,但Redis3.0.6版本之后支持迁移多个键,如果当前需要迁移多 个键,此处为空字符串""。
    ·destination-db:目标Redis的数据库索引,例如要迁移到0号数据库,这

    migrate命令也是用于在Redis实例间进行数据迁移的,实际上migrate命令就是将dump、restore、del三个命令进行
    组合,从而简化了操作流程。 migrate命令具有原子性,而且从Redis3.0.6版本以后已经支持迁移多个键的
    功能,有效地提高了迁移效率,migrate在10.4节水平扩容中起到重要作用。里就写0。
    ·timeout:迁移的超时时间(单位为毫秒)。 ·[copy]:如果添加此选项,迁移后并不删除源键。
    ·[replace]:如果添加此选项,migrate不管目标Redis是否存在该键都会正常迁移进行数据覆盖。
    ·[keys key[key…]]:迁移多个键,例如要迁移key1、key2、key3,此处填写“keys key1 key2 key3”。

2、遍历键(keys、scan)

Redis提供了两个命令遍历所有的键,分别是keys和scan,本节将对它们介绍并简要分析。

  • 1、全量遍历键
    keys 参数
    实际上keys命令是支持pattern匹配的
    *代表匹配任意字符。
    []代表匹配部分字符,例如[1,3]代表匹配1,3,[1-10]代表匹配1到10的任意数字。
    \x用来做转义,例如要匹配星号、问号需要进行转义。
    例子:
    匹配以j,r开头,紧跟edis字符串的所有键:
    keys [j,r]edis
    但是如果考虑到Redis的单线程架构就不那么美妙了,如果Redis包含了大量的键,执行keys命令很可能会造成Redis阻塞

  • 2、渐进式遍历
    Redis从2.8版本后,提供了一个新的命令scan,它能有效的解决keys命令存在的问题。和keys命令执行时会遍历所有键不同,scan
    采用渐进式遍历的方式来解决keys命令可能带来的阻塞问题,每次scan命令的时间复杂度是O(1),但是要真正实现keys的功能,
    需要执行多次scan。Redis存储键值对实际使用的是hashtable的数据结构.
    scan不是一次遍历所有的,第一次游标选择0,下一次使用上一次返回的游标作为结果,如下图的scan 5。
    在这里插入图片描述

九、数据库管理

1、切换数据库

select dbIndex

与关系型数据库用字符来区分不同数据库名不同,Redis只是用数字作为多个数据库的实现。Redis默认配置中是有16个数据库:
databases 16

那么能不能像使用测试数据库和正式数据库一样,把正式的数据放在0号数据库,测试的数据库放在1号数据库,那么两者在数据上就不会彼此受影响了。事实真有那么好吗?

Redis3.0中已经逐渐弱化这个功能,例如Redis的分布式实现Redis Cluster只允许使用0号数据库,只不过为了向下兼容老版本的数据库功能,
该功能没有完全废弃掉,下面分析一下为什么要废弃掉这个“优秀”的功能 呢?总结起来有三点:

  • 1、Redis是单线程的。如果使用多个数据库,那么这些数据库仍然是使用一个CPU,彼此之间还是会受到影响的。
  • 2、多数据库的使用方式,会让调试和运维不同业务的数据库变的困难,假如有一个慢查询存在,依然会影响其他数据库,这样会使得别的业务方定位问题非常的困难。
  • 3、部分Redis的客户端根本就不支持这种方式。即使支持,在开发的时候来回切换数字形式的数据库,很容易弄乱

2、清空数据库(flushdb/flushall)

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

flushdb/flushall命令会将所有数据清除,一旦误操作后果不堪设想,第12章会介绍rename-command配置规避这个问题,以及如何在误操作后快速恢 复数据。
如果当前数据库键值数量比较多,flushdb/flushall存在阻塞Redis的可能性。

十、章节总结

  • 1)Redis提供5种数据结构,每种数据结构都有多种内部编码实现。
  • 2)纯内存存储、IO多路复用技术、单线程架构是造就Redis高性能的三个因素。
  • 3)由于Redis的单线程架构,所以需要每个命令能被快速执行完,否则会存在阻塞Redis的可能,理解Redis单线程命令处理机制是开发和运维Redis 的核心之一。
  • 4)批量操作(例如mget、mset、hmset等)能够有效提高命令执行的效率,但要注意每次批量操作的个数和字节数。
  • 5)了解每个命令的时间复杂度在开发中至关重要,例如在使用keys、hgetall、smembers、zrange等时间复杂度较高的命令时,需要考虑数据规模 对于Redis的影响。
  • 6)persist命令可以删除任意类型键的过期时间,但是set命令也会删除字符串类型键的过期时间,这在开发时容易被忽视。
  • 7)move、dump+restore、migrate是Redis发展过程中三种迁移键的方式,其中move命令基本废弃,migrate命令用原子性的方式实现了dump+restore,并且支持批量操作,是Redis Cluster实现水平扩容的重要工 具。
  • 8)scan命令可以解决keys命令可能带来的阻塞问题,同时Redis还提供了hscan、sscan、zscan渐进式地遍历hash、set、zset。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值