Redis开发与运维学习笔记 -- 第2章 API的理解和使用

2.1 全局命令

  1. 查看所有的键
    • keys * : 对所有的key进行遍历并输出.
  2. 键总数
    • dbsize : 直接获取Redis内置的键总数变量,不会遍历所有的键
      • keys*是遍历所有的key,所以在key值很大时,不建议使用
  3. 查看键是否存在
    • exists key : 存在返回1 不存在返回0
  4. 删除键
    • del key [key...] : 任何类型都可用del
  5. 键过期
    • expire key seconds : 到时间后自动删除
    • ttl key返回key值剩余的时间
      • -1键没有设置过期时间
      • -2键不存在
      • 大于等于0的整数:键剩余的过期时间
  6. 单线程架构
    • 客户端与服务器请求过程 : 发送命令 -> 执行命令 -> 返回结果
      • 因Redis是单线程的,所以命令过来后不会立即执行,而是放到一个队列中,逐个被执行,执行顺序是不确定的,但是可以确定不会有两天命令被同时执行
    • Redis单线程快的原因
      • 纯内存访问:内存的相应时长大约是100纳秒(1秒=10亿纳秒),这是Redis达到每秒万级别访问的基础
      • 非阻塞I/O:Redis使用++epoll++作为I/O多路复用技术的实现[epoll优点:1.没有最大并发连接的限制. 2.效率提升,直管活跃的链接,而跟链接的总数无关. 3.内存拷贝,epoll使用的是’共享内存’,所以内存拷贝可省略
    • 单线程避免了现成切换和++竞态++产生的消耗
      • [竞态:我理解的竞态就是同一段代码,有概率输出不同的结果,只因有线程在读取时有其他的线程同时对该线程进行了更改操作导致的,而Redis是单线程,不需要考虑这方面]

2.2 字符串string

1.字符串类型是Redis最基础的数据结构.首先键都是字符串类型,而其他几种数据结构都是在字符串类型基础上构建的.
2.字符串类型的value可以是:字符串/数字/二进制(图片,音频,视频).但最大值不能超过512M
  1. 常用命令

    • 设置值
      • set key value [ex seconds] [px milliseconds] [nx|xx]
        • ex seconds : 为键设置秒级过期时间set hello words 2
        • px milliseconds : 为键设置毫秒级过期时间
        • nx : 键必须不存在,才可以设置成功,++用于添加++set hello words nx[等同于set前判断了下该key值是否存在,如果存在则写入失败]
        • xx : 与nx相反,键必须存在,才可以设置成功,++用于更新++
        • 如果已经设置了过期时间,再去set这个键的话,会清除该key的过期时间
    • 获取值
      • get key
    • 批量设置值
      • mset key value [key value ...] : 例:mset a 1 b 2 c 3
    • 批量获取值
      • mget key [key ...] : 键不存在,则值为nil
    • 计数
      • incr key : 例:mget a b c
        • 值不是整数,返回错误[(error) ERR value is not an integer or out of range]
        • 值是整数,返回自增后的结果
        • 键不存在,按照值为0自增,结果返回1
        • 增加指定数量incrby key increment : 返回增加指定数量后的数字
        • 增加指定小数incrbyfloat key increment : 返回增加指定数量后的数字
    • 减数
      • decr key : 返回减后的数字,可减到负数
        • 减少指定数量decrby key decrement : 返回减少指定数量后的数字
  2. 不常用命令

    • 追加值
      • append key value : 向字符串尾部追加值
    • 字符段长度
      • strlen key : 每个中文占3个字节
    • 设置并返回值
      • getset key value : 设置值后同时返回key原来的value,如果此key值之前是空的,则返回nil
    • 获取部分字符数串
      • getrange key start end : 如超出了原有的长度,则直接忽略超出的长度,不会用占位符显示
    • 设置指定位置的字符
      • setrange key offset value : 下标从0开始,替换该位置的值,如果下标超出原有的长度,中间的位置会用\x00占位↓
127.0.0.1:6379[15]> get testNc
"word"
127.0.0.1:6379[15]> setrange testNc 8 s
(integer) 9
127.0.0.1:6379[15]> get testNc
"word\x00\x00\x00\x00s"
  1. 内部编码
    • int : 8个字节的长整型
    • embstr : 小于等于44个字节
    • raw : 大于44个字节
      • object encoding key查看该key值的内部编码类型,如果原本是int类型的,但因长度到了45个字节变成了raw编码类型,就算后期有删除字节数,内部编码也会是raw,而不会减

2.3 哈希hash

1.在Redis中,哈希类型是指键值本身又是一个键值对结构,形如`value={{filed1,value1},{filed2,value2}...{feiedN,valueN}}`
2.哈希类型中的映射关系叫做filed-value,这里的value是指filed对应的值,不是value键值对里面的value值,如1中所示,value是整个{},而不是{}里面的任意{value1,value2...}
  1. 常用命令

    • 设置值
      • hset key filed value
        • 批量设置hmset key field value {field value ...}
        • 设置不重复的值hsetnx key field value : 用hsetnx设置值,key中的field不能重复,如重复则设置失败,hsetnx不能拆分成hset key field value nx
    • 获取值
      • hget key filed : 如键值或者filed不存在,则返回nil
        • 批量获取 hmget key field {field}
        • 获取所有的field.hkeys key : key不能用*代替,需明确指出key值,而后返回该key值内所有的field[不包括field中的value]
        • 获取所有的value.hvals key : 获取该key的所有value,和hmget不同的是,不需要指定获取key中的哪个field,而是可以获取该key的全部value[不包括field]
    • 删除filed
      • hdel key field [field ...] : hdel会删除一个或多个field,返回的结果为成功删除field的个数.[和del相比,del是把整个key删除了,而hdel只是删除key中的某个field]
    • 计算field的个数
      • hlen key : 计算该key中有多少组键值对
        • 计算field的value个数 hstrlen key field : 需要Redis3.2版本以上
    • 判断field是否存在
      • hexists key field : 存在返回1,不存在返回0
    • 获取所有的field-value.
      • hgetall key : 返回的顺序是field value field value …顺序
        • 在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能,所以如果只需要获取不分的field,建议使用hmget,也有介绍说使用hscan的,但是至今未弄明白
    • 累加数
      • 整数hincrby key field increment
      • 小数hincrbyfloat key field increment
        • 哈希中的计数作用域是key里field的value,而string的作用域直接是key的value
  2. 内部编码

    • ziplist(压缩列表) : 当哈希类型元素小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64字节).++节省内存方面比hashtable更优秀++
    • hashtable(哈希表) : 当哈希类型无法满足ziplist时,则使用hashtable作为哈希的内部实现
      • 配置是Redis安装位置里的redis.conf文件
  3. 注意事项

    • 哈希类型与关系型数据库不同之处
      • 哈希类型是稀疏的,而关系型数据库是完全结构化的[哈希类型可以一个个field添加,而关系型数据库如果添加一个key的话,则需要把下面所有的field全部为期设置value,哪怕设置的value是NULL]
      • 关系型数据库可以做复杂的关系查询,而Redis去模拟关系型复杂查询开发困难,维护成本高

2.4 列表list

1.列表类型是用来存储多个有序的字符串,列表中每个字符串称之为元素(element)
2.一个列表最多存储2的32次方-1个元素(4294967295个)
3.列表是一种比较灵活的数据结构,它可以充当栈和队列的角色
4.列表中的特点:
    4.1 列表中的元素是有序的(下标从0开始)
    4.2 列表中的元素可以是重复的
  1. 常用命令

    • 添加操作++[开头的L和R代表的left->>> right<<<- 插入方向不同]++
      • rpush key value [value ...] : 从右向左插入<<<-
      • lpush key value [value ...] : 从左向右插入->>>
      • linsert key before|after pivot value : 向某个元素前或者后插入数据
        • insert命令会从列表中找到等于pivot的第一个元素,在其前(before)或者后(after)插入一个新元素value
    • 查找
      • lrange key start end : lrange操作会获取列表指定索引范围所有的元素,start = 0,end = -1,则是获取该key的全部元素,下标从0开始,查出的数据都是包含start和end自身的
      • lindex key index : 获取列表指定索引下标的元素
      • llen : 获取列表长度
    • 删除
      • lpop key : 从列表左侧弹出元素,返回被弹出的元素后,该list将减少1
      • rpop key : 从列表右侧弹出元素
      • lrem key count value : 根据count的不同分为三种情况
        • count > 0 : 从左到右,删除最多count个等于该value的元素
        • count < 0 : 从右到做,删除最多count个等于该value的元素
        • count = 0 : 删除所有等于该value的元素
      • ltrim key start end : 按照索引范围修剪列表,只保留该key值的 start -> end 下标的元素
    • 修改
      • lset key index newValue : 修改制定索引下标的元素
        • 如果下标超出已有的数量,则会返回错误(error) ERR index out of range
    • 阻塞操作
      • blpop key [key ...] timeout : timeout是阻塞的时间(以秒为单位)
      • brpop key [key ...] timeout : 1.如果是多个键,那么brpop会从左至右遍历键,一旦有一个能弹出的则立即返回,后面的键则忽略. 2.如果是多个客户端对同一个键进行brpop,那么最先执行此命令的客户端最先获取值,如值不够,其余的客户端继续阻塞,直至有值可以取出
        • 如果timeout = 3,那么要等待3秒才会返回结果(如key为空则返回nil)
        • 如果timeout = 0 ,则立即返回(如key为空,则会一直阻塞下去,直到此key值有数据弹出为止)
  2. 内部编码

    • ziplist(压缩列表) : 当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置(默认64个字节)
    • linkedlist(链表) : 当列表类型无法满足ziplist条件时,Redis会使用Linkedlist作为列表的内部实现
      • 配置是Redis安装位置里的redis.conf文件
  3. 开发提示

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

2.5 集合

1.集合(set)类型也是用来保存多个字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素
2.一个集合最多可以存储2的32次方-1个元素(4294967295个)
  1. 常用命令

    • 集合内操作
      • sadd key element [element ...] : 添加元素,返回成功添加的元素个数
      • srem key elemnet [element ...] : 删除元素,返回成功删除的元素个数
      • scard key : 计算元素个数,它不会遍历集合所有元素,而是直接用Redis内部的变量
      • sismember key element : 判断元素是否在集合中(exists key则是判断是否有该集合),如有则返回1,没在则返回0
      • srandmember key [count] : 随机从集合中返回count个元素,不写则默认为1
      • spop key : 从集合随机弹出元素,返回被弹出的元素.不接受弹出指定元素,如需指定,可用srem.[Redis从3.2版本后,spop支持count参数],被弹出的元素会被删除
      • smembers key : 获取所有元素,结果是无序的
        • smemberslrangehgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan(批量查找key中的元素)来完成
    • 集合间的操作
      • sinter key [key ...] : 求多个集合的交集,就是多个key中,相同的元素
      • sunion key [key ...] : 求多个集合的并集,就是求多个key中所有的元素,但是重复的元素只显示一次
      • sdiff key1 [key2 ...] : 求多个集合的差集,返回的是key1里面其他key中所没有的元素
      • 将交集、并集、差集的结果保存
        • sinterstore destination key [key ...]
        • sunionstore destination key [key ...]
        • sdiffstpre destination key [key ...]
        • 以上三种都是讲查询出的结果放到destination中,如果该distination已经存在,则会覆盖原数据
  2. 内部编码

    • intset(整数集合) : 当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)
    • hashtable(哈希表) : 当集合类型无法满足intset的条件或当某个元素不为整数时时,Redis会使用hashtable作为集合的内部实现.
  3. 开发需要

    • sadd = Tagging(标签)
    • spop/srandmember = Random item(生成随机数,比如抽奖)
    • sadd + sinter = Social Graph(社交需要)

2.6 有序集合

1.它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序
2.但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置了一个分数(score)作为排序的依据
3.有序集合中的元素不能重复,但是score是可以重复的,就像一个班级中学号不能重复,但是考试成绩可以重复的概念一样
  1. 常用命令

    • 添加成员
      • zadd key score member [score member ...] : 返回结果代表成功添加成员的个数,如该成员已经存在,会覆盖原分数,并返回0
        • Redis3.2为zadd命令添加了nx、xx、ch、incr四个选项
          • nx : member必须不存在,才可以设置成功,用于添加
          • xx : member必须存在,才可以设置成功,用于更新
          • ch : 返回此次操作后,有序集合元素和分数发生变化的个数
          • incr : 对score做增加,相当于zincrby
        • 有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度是O(log(n)),sadd的时间复杂度是O(1)
    • 计算成员个数
      • zcard key : 返回该key的成员个数
    • 查看某个成员的分数
      • zscore key member
    • 计算成员排名
      • zrank key member : 从低到高排序的名次
      • zrevrank key member : 从高到底排序的名次
    • 删除成员
      • zrem key member [member ...] : 返回成功删除的个数
    • 增加成员指定的分数
      • zincrby key increment member : 返回增加指定分数后的score,它和zadd不同的是,如果该成员已经存在,zadd是覆盖原分数,而zincrby是在原有的分数上进行累加指定分数
    • 返回指定排名范围的成员
      • zrange key start end [withscores] : 从低到高排序后返回指定下标内的成员
      • zrevrange key start end [withscores] : 从高到底排序后返回指定下标内的成员
        • 下标从0开始
        • start = 0, end = -1就是返回全部的成员
        • 后面加withscores就是不仅返回成员的名字,同时也会返回该成员的分数
    • 返回指定分数范围的成员
      • zrangebyscore key min max [withscores] [limit offset count] : 返回分数在min和max之间分数的成员,并由低到高进行排序返回
      • zrevrangebyscore key max min [withscores] [limit offset count] : 返回分数在max和min之间分数的成员,并由高到低进行排序返回
        • -inf+inf分表代表着无限小和无限大
        • minmax支持开区间(小括号)和闭区间(中括号),如不带符号,默认闭区间,包含此分数.如果分数前带小括号,则本次查询不包含此分数.
        • zrangebyscore key (10 +inf withscores 此次查询返回的是该key中包含10分并且比10分大的所有成员和分数.
    • 返回指定分数范围成员个数
      • zcount key min max : 返回的是包含min和max分数的成员个数
    • 删除指定排名内的升序元素
      • zremrangebyrank key start end : 下标从0开始,返回成功删除的个数
    • 删除指定分数范围的成员
      • zremrangebyscore key min max : 此位置可用-inf,+inf,(,返回成功删除的个数
  2. 集合间的操作

    • 交集
      • 就是多个key中,相同的元素
      • zinterscore destination numkeys key [key ...] [weights weight [weight]] [aggregate sum|min|max]
        • dstination : 交集计算记过保存到这个键,如存在,则覆盖原数据
        • numkeys : 需要做交集计算键的个数,用几个key做交集,这就写几
        • key [key ...] : 需要做交集计算的键
        • weights weight [weight ...] : 每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,每个键默认权重是1
        • aggregate sum|min|max : 计算成员交集后,分值可以按照sum,min,max做汇总,默认是sum,计算这几个key中共同拥有的成员分数总和
        • 举例 : ++zinterscore++ ++copyKey++ ++3++ ++testZadd1 testZadd2 testZadd3++ ++weights 1 0.5 2++ ++aggregae max++ .每个下划线对应一个命令参数,像weights,aggregae这种命令参数是需要写上的,后面跟着具体的命令,weights是可以用小数的
    • 并集
      • 就是求多个key中所有的元素,但是重复的元素只显示一次
      • zunionstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate sum|min|max] : 命令的所有参数和并集里面的一夜,只不过做的是并集计算
  3. 内部编码

    • ziplist(压缩列表) : 当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节),ziplist可以有效减少内存的使用
    • skiplist(跳跃表) : 当ziplist条件不满足时,有序集合会使用skiplist作为内部实现

2.7 键管理

  1. 单个键管理

    • 键重命名
      • rename key newkey : 如果newkey之前就已经存在,那么本次的操作会把key的值覆盖原有的值
      • 为了防止被强行rename,建议使用renamenx命令,确保newkey是不存在的
        • 由于重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性
    • 随机返回一个键
      • randomkey
    • 键过期
      • expire key seconds : 键存在second秒后过期,秒级
      • expireat key timestamp : 键在秒级时间戳timestamp后过期
      • pexpire key milliseconds : 键存在milliseconds秒后过期,毫秒级
      • pexpireat key milliseconds-timestamp : 键在毫秒级时间戳timestamp后过期
        • ttl key : 查看key的过期剩余时间,秒级
        • pttl key : 查看key的过期剩余时间,毫秒级
        • persist key : 可以清除键的过期时间
        • 对于字符串类型的键,执行set命令也会去掉过期时间
        • Redis不支持二级数据结构(例如哈希,列表)内部元素的过期功能
        • setex命令作为set+expire的组合,不但是原子执行,同时减少了一次网络通讯的时间
    • 迁移键
      • move key db : move命令用于在Redis内部进行数据迁移,就是把指定的键从源数据库迁移到目标数据库,不建议在生产环境试验
      • dump + restore : 可以实现不同Redis实例之间进行数据迁移的功能,分为两个步骤
          1. dump key : 在源Redis上,dump命令会将键值序列化,格式采用的是RDB格式,执行后返回的是类似这种的"\x0c$$\x00\x00\x00!\x00\x00\x00\n\x00\x00\x01c\x03\xf3\x02\x01a\x03\xf7\x02\x01b\x03\xfb\x02\x01n\x03\xfc\x02\x01s\x03\xfc\xff\b\x00Z\x1bo\xb4\x97\x89\xd1w"作为restore命令的value
          1. restore key ttl value : 在目标Redis上,restore命令会将上面序列化的值进行复原,其中ttl参数代表过期时间,如果不需要过期,则再ttl的位置写0
          • 可低版本Redis上dump,高版本的restore,反之则会报错,如果Redis版本一致则无需关心
      • migrate host port key|"" detination-db timout [copy] [replace] [keys key [key ...]] : migrate命令也是用于在Redis实例之间数据迁移的,实际上migrate命令就是将dump,restore,del三个命令组合了
        • migrate命令具有原子性
        • migrate命令的数据传输直接在源Redis和目标Redis上完成的
        • 目标Redis完成restore后会发送OK给源Redis
        • host : 目标Redis的IP地址
        • port : 目标Redis的端口
        • key|"" : 在Redis3.0.6版本之前,migrate只支持一个键,所以此处写要迁移的键.但Redis3.0.6版本后支持迁移多个键,所以要迁移多个的时候,此处为空字符""
        • destination-db : 目标Redis的数据库索引
        • timeout : 迁移的超时时间(单位毫秒)
        • [copy] : 如果添加此选项,迁移后并不删除原键.如果不添加此选项,源Redis会删除迁移的key
        • relace : 如果添加此选项,migrate不管目标Redis是否存在都会正常迁移进行数据覆盖
        • [keys key [key ...]] : 迁移多个键
  2. 遍历键

    • 2.1 全量遍历键
      • keys pattern : 平时最常用的就是keys *,也就是获取所有的键
        • * : 代表匹配任意字符,0-多个
        • ? : 代表匹配一个字符.keys h?ll*,可以匹配类似hello,hill这种符合条件的键
        • [] : 代表匹配不分字符,例如[1,3]代表匹配该key中有1或3的.[1-10]代表匹配1到10的任意数字.keys [j,r]edis, 就是匹配以j或r开头,紧跟着edis的所有键
        • \x用来做转义,例如要匹配星号,问号这种就需要转义
      • 如键过多,不建议使用,容易阻塞
    • 渐进式遍历
      • 一个不太明白的命令
      • scan cursor [match pattern] [count number] : scan赛用渐进式遍历的方式来解决keys命令可能带来的阻塞问题
        • cursor : 是必须参数,实际上cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值
        • match pattern : 是可选参数,它的作用是模式的匹配,这点和keys的模式匹配很像
        • count number : 是可选参数,表名每个要遍历的键的个数,默认是10
      • 如果scan的过程中如果有键的变化(增删改的动作),那么遍历效果可能会碰到如下问题 : 1.新增的键可能没有遍历到; 2.遍历出重复的键等情况.也就是说scan并不能保证完整的遍历出来所有的键
  3. 数据库管理

    • 切换数据库
      • select dbIndex
    • 清除数据库
      • flushdb : 清除所在的数据库
      • flushall : 清除0-15所有的数据库
        • 如果数据过多,会存在阻塞的可能

版权声明:本文为weixin_43239068原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。