Redis基础

Redis安装

官网下载最新稳定版本的压缩包,解压缩后放到任意目录下,进行解压后的目录执行:

make (编译代码)
make install (安装)

安装后执行redis-cli-v查看Redis版本号

Redis启动

最好复制一个配置文件放到一个文件夹下,并在配置文件中修改daemonize yes,表示开启守护线程,启动时指定配置文件

redis-server (–configKey1 configValue1 –configKey2 configValue2)

redis-server 配置文件所在地址

没指定则使用默认配置

Redis命令行客户端

  • 连接redis
    不使用h表示使用默认ip和默认端口

    redis-cli -h {host} -p {port} ({command})

  • 关闭redis

    redis-cli shutdown (nosave|save) 是否生成持久化文件

Redis常用命令

  1. 查看所有键

    keys *

  2. 键总数

    dbsize

  • keys和dbsize的区别:
    dbsize直接获取redis内置的键总数,时间复杂度是O(1),keys命令遍历所有键,时间复杂度是O(n),线上禁止使用
  1. 检查键是否存在

    exists key

  2. 删除键

    del key1,key2,…

  3. 设置键过期时间

    expire key seconds

  4. 返回键剩余时间
    没有设置时间返回-1,没有这个键返回-2

    ttl keys

  5. 键的数据类型

    type key

数据结构和内部编码

redis有一下几种数据结构类型:string,hash,list,set(集合),zset(有序集合),每种数据结构都有自己的内部编码,可以通过一下命令查看内部编码

object encoding key

内部编码

单线程架构

从客户端发送到redis的所有命令不会被立即立即执行,会被放在一个队列中,然后逐个执行,所以客户端命令的执行顺序是不确定的。

基本数据结构

字符串

是redis最基础的数据结构,包括字符串,数字,二进制(最大不超过512Mb)

常用命令

  1. 设置值

    set key value [ex seconds] [px milliseconds] [nx|xx]
    setnx 相当于set加上nx,表示当键不存在时才能插入,用于插入数据
    setex 相当于set加上ex
    xx表示键已经存在,用于更新
    mset key value key value … 批量插入多个键值对

  2. 获取值

    get key
    mget key key … 批量获取多个值

批量操作能够将藕提高开发效率,减少多次网络请求的时间,一次性发出,一次性接收

  1. 计数
    对值做自增操作,如果值不是整数则报错,如果原来的键不存在,则会自动创建并按0自增为1

    incr key

此外还提供了decr(自减),incrby(自增指定数值),decrby(自减指定数字),incrbyfloat(自增浮点数)

  1. 其他

    append key value 在字符串末尾追加
    strlen key 获取字符串长度,中文占用3个字节
    getset key value 设置并返回原来的值
    setrange key offset value 设定指定位置的字符
    getrange key start end 获取部分字符串

内部编码

  • int:8个字节的长整型
  • embstr:小于等于39个字节的字符串
  • raw:大于39个字节的字符串

使用场景

  1. 缓存功能
  2. 计数
  3. 共享session
  4. 限速

哈希

哈希类型指键值本身又是一个键值对的结构,其形式如下图:
hash存储方式

常用命令

hset key field value 还有hsetnx,作用域是filed
hget key field
hdel key field [field …] 删除一个或者多个field,返回删除个数
hlen key 计算field个数
hmget key field [field …]
hmset key field [key field …]
hexists key field 判断field是否存在
hkeys key 获取所有field
hvals key 获取所有value
hgetall key 获取所有的field-value
hincrby key field
hincrbyfloat key field 作用域都是field
hstrelen key field

如果哈希元素比较多,会存在Redis阻塞的可能,尽量使用hmget

内部编码

  • ziplist(压缩列表)
    当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512字节),同时所有值小于hash-max-ziplist-value配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀
  • hashtable(哈希表)
    当哈希类型无法满足ziplist的条件时,使用hashtable作为内部实现,因为此时ziplist读写效率会下降,而hashtable读写时间复杂度为O(1)

使用场景

将关系型数据库每一行数据存储为一个哈希键

列表

列表(list)用来存储多个有序的字符串,列表总每个字符串称为元素(element),一个列表最多可以存储2^32-1个元素,可以充当栈和队列

常用命令

  1. 添加

    rpush key value [value…] 在右边依次插入元素
    lpush key value [value…] 在左边依次插入元素
    linsert key before|after pivot value 向某个元素的前或后插入元素

  2. 查找
    索引下标从左到右是0到N-1,但从右到左是 -1到-N

    lrange key start end 指定范围内的元素列表,end包含了自身(0到-1表示查询所有)
    lindex key index 获取列表指定索引下标的元素
    llen key 获取列表长度

  3. 删除

    lpop key 从左侧弹出删除元素
    rpop key 从右侧删除
    lrem key count value 删除指定元素
    ltrim key start end 按照索引范围截取列表

lrem命令会从列表中找到等于value的元素进行删除:

  • count>0 从左到右,删除最多count个元素
  • count<0 从右到左,删除count的绝对值个元素
  • count=0 删除所有
  1. 修改

    lset key index newValue

  2. 阻塞操作

参数key为多个列表的键,timeout为阻塞时间

blpop key [key …] timeout
brpop key [key …] timeout

  • 列表为空
    如果timeout不等于0,则等待相应秒数后返回,如果timeout=0,那么客户端一直阻塞下去,此时如果另一个客户端添加了数据element1,客户端立即返回
  • 列表不为空
    客户端会立即返回,如果有多个键,只会弹出第一个键并返回

注意事项
如果多个客户端对同一个键执行brpop,当列表只有一个元素时,最先执行的客户端可以获取到弹出的值,其他的会继续阻塞

内部编码

  • ziplist(压缩列表)
    当哈希类型元素个数小于list-max-ziplist-entries配置(默认512),同时所有值小于list-max-ziplist-value配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀
  • linkedlist(链表)
    当哈希类型无法满足ziplist的条件时,使用linkedlist作为内部实现。

使用场景

  1. 栈,队列
  2. 消息队列(抢购)
  3. 文章列表

集合

集合(set)可以保存多个字符串元素,但是不允许有重复元素,并且集合中的元素是无序的,一个集合最多可以存储2^32-1个元素,集合可以进行内部的增删改查和多个集合取交集,并集,差集

基本命令

  1. 集合内操作

添加元素

sadd key element [element …]

删除元素 Redis内部变量

srem key element [element …]

计算元素个数,空间复杂度为O(1),直接使用redis中的变量

scard key

判断给定元素是否在集合中

sismenber key element

随机从集合中返回指定个数的元素

srandmember key [count]

从集合中随机弹出元素

spop key

获取所有元素

smembers key

  1. 集合间操作

求多个集合的交集

sinter key [key …]

求多个集合的并集

sunion key [key …]

求多个集合的差集

sdiff key [key …]

将交集、并集、差集的结果保存到指定的key中

sinterstore destiantion key [key …]
sunionstore destination key [key …]
sdiffstore destination key [key …]

内部编码

  • intset(整数集合)
    当集合中的元素都是整数而且与元素个数小于set-max-intset-entries配置(默认512个)时,使用该编码减少内存的使用
  • hashtable(哈希表)
    其他条件下使用哈希表作为内部实现

使用场景

  1. 标签
  2. 生成随机数(抽奖)
  3. 社交需求

有序集合

有序集合(zset)保留集合元素不能重复的特性,但是有序集合中的元素可以排序,它为每一个元素设定一个score作为排序的依据
有序集合结构

常用命令

  1. 集合内

添加成员,时间复杂度为O(log(n))

zadd key score member [score member …]

参数

  • nx member必须不存在
  • xx member必须存在
  • ch 返回此次操作后,有序集合元素和分数发生变化的个数
  • incr 对score做增加

计算成员个数

zcard key

计算某个成员的分数

zscore key member

计算成员排名,从0开始算

zrank key member 从低到高
zrevrank key member 从高到低

删除成员

zrem key member [member …]

增加指定分数

zincrby key increment member

返回指定排名范围的成员

zrange key start end [withscores]
zrverange key start end [withscores]

返回指定分数范围的成员,limit可以限制输出的起始位置位置和个数,同时min和max还支持开区间(小括号)和闭区间(中括号),-inf表示负无穷,+inf表示正无穷

zrangebyscore key min max [withscores] [limit offset count]
zrverangebyscore key max min [withscores] [limit offset count]

返回指定分数范围的成员个数

zcount key min max

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

zremrangebyrank key start end

删除指定分数范围的成员

zremrangebyscore key min max

  1. 集合间的操作

交集

zinterstore destination numkeys key [key …] [weights weight [weight …]] [aggregate sum|min|,max]

  • destination:交集结果保存在这个键
  • numkeys:需要做交集计算键的个数
  • key[key…]:需要做交集计算的键
  • weights:每个键的权重,做交集运算时会将自身分数乘上权重,默认是1
  • aggregate sum|max|min:计算交集后的分值可以是和、最大值、最小值,默认是sum

并集

zunionstore destination numkeys key [key …] [weights weight [weight …]][aggregate sum|min|max]

内部编码

  • ziplist(压缩列表)
    当哈希类型元素个数小于zset-max-ziplist-entries配置(默认128个),同时所有值小于zset-max-ziplist-value配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀
  • skiplist(跳跃表)
    当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降

使用场景

  1. 排行榜系统
  2. 用户点赞

键管理

单个键管理

键重名:如果在rename之前该键已经存在,则其值也会被覆盖掉,可以使用renamenx, 确保只有当newKey不存在时才能执行。
由于重命名期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性

rename key newkey

随机返回一个键

randomkey

键过期
键在seconds秒之后过期

expire key seconds

键在秒级时间戳timestamp后过期

expireat key timestamp

设置毫秒级过期时间

pexpire key milliseconds 在milliseconds毫秒后过期
pexpireat key milliseconds-timestamp 在毫秒级时间戳后过期

  • 无论使用过期时间是秒还是时间戳,秒级还是毫秒级,redis内部最终使用pexpireat

查看剩余过期时间,-1表示没有设置过期时间,-2表示键不存在,大于等于0的整数表示剩余时间

ttl keys
pttl keys 精度更高,达到毫秒级

使用键过期的注意事项:

  1. 如果expire key的键不存在,返回结果为0
  2. 如果过期时间设置为负值,键会立即被删除,相当于del
  3. persist可以将键的过期时间清除
  4. 对于字符串类型键,执行set命令会去掉过期时间
  5. redis不支持二级数据结构(例如哈希,列表)内部元素的过期功能
  6. setex命令作为set+expire的组合,是原子执行,同时减少一次网络通讯的时间

迁移键

redis中可以有多个数据库,彼此相互隔离,将指定的键从当前数据库迁移到目标数据库

move key db

在不同redis之间执行数据迁移,该操作不具备原子性,需要在两个客户端进行操作

dump key 返回value
restore key ttl value value为上面的值

该过程分为两步:

  • 在源redis上,dump命令将键值序列化,格式采用RDB格式
  • 在目标redis上,restore命令将上面序列化的值复原,ttl参数代表过期时间,等于0代表没有过期时间

migrate命令也用于在不同redis之间迁移,它将move、dump、restore进行整合,具有原子性,只需要在一个客户端就可以执行完成,同时支持多个键进行迁移

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

  • host:目标redis的ip地址
  • port:目标redis的端口
  • key|””:迁移一个键为key,多个键为空字符串“”
  • destination-db:目标Redis数据库索引,例如0号数据库,就写0
  • timeout:迁移的超时时间,单位为毫秒
  • copy:如果添加此选项,迁移后不删除源键
  • replace:如果添加此选项,migrate不管目标redis是否存在该键都会进行迁移并进行数据覆盖
  • keys key …: 迁移的多个键

migrate执行过程

遍历键

全量遍历键

keys pattern

pattern使用glob风格的通配符:

  • *代表匹配任意字符
  • 任意一个字符代表匹配一个字符
  • ?代表匹配一个字符
  • []代表匹配部分字符,[1,3]代表匹配1,3,[1-10]代表匹配1到10的任意数字
  • \ x 用来做转移,例如问号,星号等

如果Redis包含了大量的键,使用keys可能会造成阻塞

渐进式遍历

scan cursor [match pattern] [count number]

scan采用渐进式遍历,要扫描所有需要多次执行,可以一定程度上避免阻塞
参数说明:

  • cursor:游标,第一次从0开始,每次执行完scan会返回下一次的游标,直到返回0表示遍历结束
  • match pattern:遍历匹配
  • count nnumber 每次遍历的键个数,默认10

对于hgetall,smembers,zrange可能产生的阻塞问题,对应的命令分别为hscan,sscan,zscan
在执行scan的过程中,如果有键发生变化(增加、删除、修改),可能会产生新增的键没有遍历到,遍历出重复的键等问题

数据库管理

一个Redis中可以有多个数据库实例,使用数字索引区分,默认配置有16个数据库

切换数据库

select daIndex

清除数据库

清除当前数据库

flushdb

清除所有数据库

flushall