CodeAshen's blog CodeAshen's blog
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)

CodeAshen

后端界的小学生
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)
  • MySQL8.0详解与实战

  • MySQL面试指南

  • Redis从入门到高可用

    • 第01章-初识Redis
    • 第02章-API理解和使用
      • 1.1 通用命令
      • 1.2 数据结构和内部编码
      • 1.3 单线程架构
      • 2.1 字符串键值结构
      • 2.2 字符串命令
      • 3.1 哈希键值结构
      • 3.2 哈希命令
      • 4.1 列表介绍
      • 4.2 列表API
    • 第03章-Redis客户端
    • 第04章-Redis其他功能
    • 第05章-Redis持久化
    • 第06章-Redis主从复制
    • 第07章-Redis Sentinel
    • 第08章-Redis Cluster
    • 第09章-缓存设计与优化
    • 第10章-Cache Cloud
  • Elastic-Stack

  • 数据库
  • Redis从入门到高可用
CodeAshen
2023-02-10
目录

第02章-API理解和使用

# 一、通用命令和架构

# 1.1 通用命令

  • keys [pattern]:遍历所有的 key

    127.0.0.1:6379> mset hello world hehe haha php good phe his 
    OK 
    127.0.0.1:6379> keys he* 
    1)"hehe"
    2)"hello"
    127.0.0.1:6379> keys he[h-]* 
    1)"hehe"
    2)"hello"
    127.0.0.1:6379> keys ph?
    1)"phe"
    2)"php"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    keys 一般不再生产环境使用,O(n) 复杂度

    keys * 怎么用:

    • 热备从节点
    • scan
  • dbsize:计算 key 的总数

    127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4 
    OK 
    127.0.0.1:6379> dbsize 
    (integer) 4 
    127.0.0.1:6379> sadd myset a b c d e 
    (integer) 5 
    127.0.0.1:6379> dbsize 
    (integer) 5
    
    1
    2
    3
    4
    5
    6
    7
    8

    时间复杂度 O(1),redis 内部有计数器

  • exists <key>:检查 key 是否存在

    127.0.0.1:6379> set a b 
    OK 
    127.0.0.1:6379>get a 
    "b"
    127.0.0.1:6379> del a 
    (integer) 1 
    127.0.0.1:6379> get a 
    (nil)
    
    1
    2
    3
    4
    5
    6
    7
    8
  • del [key ...]:删除指定 key-value

    127.0.0.1:6379> set a b 
    OK 
    127.0.0.1:6379> get a 
    "b"
    127.0.0.1:6379> del a 
    (integer) 1 
    127.0.0.1:6379> get a 
    (nil)
    
    1
    2
    3
    4
    5
    6
    7
    8
  • expire key <seconds>:设置 key 过期时间

    • ttl <key>:查看 key 剩余过期时间
    • persist <key>:取消过期时间
  • type <key>:返回一个 key 的类型

    127.0.0.1:6379> set a b 
    OK 
    127.0.0.1:6379> type a 
    string
    127.0.0.1:6379> sadd myset 1 2 3 
    (integer) 3
    127.0.0.1:6379> type myset
    set
    
    1
    2
    3
    4
    5
    6
    7
    8

    type 返回类型:string、hash、list、set、zset、none(不存在的 key)

常见通用命令的时间复杂度:

命令 时间复杂度
keys O(n)
dbsize O(1)
del O(1)
exists O(1)
expire O(1)
type O(1)

# 1.2 数据结构和内部编码

Redis数据结构和内部编码

Redis 对外的五种数据类型,出于性能和空间的考虑,在其内部采用不同的数据结构来实现。用户只需要关心对外提供的数据类型的使用,不关心内部实现方式,面向接口的设计。

实际在 Redis 源码内部,有一个 redisObject 的结构体,来对外实现不同的数据类型,其内部结构如下图:

image-20210601080813355

# 1.3 单线程架构

Redis 使用单线程串行执行命令

Redis单线程

单线程为什么这么快?

  1. 纯内存(主要原因)
  2. 非阻塞 IO
  3. 避免线程切换和竞态消耗

Redis非阻塞IO

单线程执行命令的特点:

  1. 一次只执行一条命令

  2. 拒绝长(慢)命令

    keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collection)

  3. 其实不是单线程

    fsync file descriptor:持久化文件

    close file descriptor:关闭文件描述符

    上述文件操作都是单独线程来执行的

# 二、字符串类型

# 2.1 字符串键值结构

image-20210601082610549

  • 字符串 key 是字符串,value 可以存字符串、数字、bits(二进制)、json 字符串等
  • 字符串 value 不能大于 512MB

字符串应用场景有:缓存、计数器、分布式锁等

# 2.2 字符串命令

API 描述 时间复杂度
get key 获取 key 对应的 value O(1)
set key value 设置 key-value O(1)
del key 删除 key-value O(1)
incr key key 自增 1,如果 key 不存在,自增后 get(key)=1 O(1)
decr key key 自减 1,如果 key 不存在,自减后 get(key)=-1 O(1)
incrby key k key 自增 k,如果 key 不存在,自增后 get(key)=k O(1)
decrby key k key 自减 k,如果 key 不存在,自减后 get(key)=-k O(1)
setex key value key 不存在,才设置 O(1)
set key value xx key 存在,才设置 O(1)
mget k1 k2 k3.. 批量获取 key,原子操作 O(n)
mset k1 v1 k2 v2 k3 v3 批量设置 key-value O(n)
getset key newValue set key newValue 并返回旧的 value O(1)
append key value 将 value 追加到旧的 value O(1)
strlen key 返回字符串的长度(注意中文) O(1)
incrbyfloat key 3.5 增加 key 对应的值 3.5 O(1)
getrange key start end 获取字符串指定下标所有的值(从 0 开始,包含首位) O(1)
setrange key index value 设置指定下标所有对应的值 O(1)

# 三、哈希类型

# 3.1 哈希键值结构

哈希键值结构

# 3.2 哈希命令

API 描述 时间复杂度
hget key field 获取 hash key 对应的 field 的 value O(1)
hset key field value 设置 hash key 对应 field 的 value O(1)
hdel key field 删除 hash key 对应 field 的 value O(1)
hexists key field 判断 hash key 是否有 field O(1)
hlen key 获取 hash key field 的数量 O(1)
hmget key field1 field...fieldN 批量获取 hash key 的一批 field 对应的值 O(n)
hmset key field1 v1 field2 v2...fieldN vN 批量设置 hash key 的一批 field value O(n)
hincrby key field k 指定 key 下 field 的值自增 k O(1)
hgetall key 返回 hash key 对应所有的 field 和 value O(n)
hvals key 返回 hash key 对应所有 field 的 value O(n)
hkeys key 返回 hash key 对应所有 field O(n)
hsetnx key field value 设置 hash key 对应 field 的 value(如 field 已经存在,则 失败) O(1)
hincrby key field intCounter hash key 对应的 field 的 value 自增 intCounter O(1)
hincrbyfloat key field floatCounter hincrby 浮点数版 O(1)

# 四、列表类性

# 4.1 列表介绍

Redis 中的列表,其实是 linked list,链表

image-20210603142646951

image-20210603142732407

列表有如下特点

  • 有序的
  • 可以重复
  • 左右两边插入和弹出

# 4.2 列表API

API 描述 时间复杂度
增
rpush key v1 v2...vN 从列表右端插入值(1-N 个) O(1~n)
lpush key v1 v2...vN 从列表左端插入值(1-N 个) O(1~n)
linsert key before\|after value newValue 在 list 指定的值前/后插入 newValue O(n)
删
lpop key 从列表左侧弹出一个item O(1)
rpop key 从列表右侧弹出一个item O(1)
lrem key count value 根据 count 值,从列表中删除所有 value 相等的项
(1)count>0,从左到右,删除最多 count 个 value 相等的项
(2)count<0,从右到左,删除最多 Math.abs(count) 个 value 相等的项
(3)count=0,删除所有 value 相等的项
O(n)
Itrim key start end 按照索引范围修剪列表(subList) O(n)
查
lrange key start end 获取列表指定索引范围所有 item(包含end) O(n)
lindex key index 获取列表指定索引的item O(n)
llen key 获取列表长度 O(1)
改
lset key index newValue 设置列表指定索引值为 newValue O(n)
Other
blpop key timeout Ipop 阻塞版本,timeout 是阻塞超时时间,timeout=0 为永远不阻塞
针对空列表,空列表 lpop 会直接返回空,blpop 会阻塞等有元素返回
O(1)
brpop key timeout rpop 阻塞版本,timeout 是阻塞超时时间,timeout=0 为永远不阻塞
针对空列表,空列表 rpop 会直接返回空,blpop 会阻塞等有元素返回
O(1)

Tips:

  • lpush + lpop = Stack(栈)
  • lpush + rpop = Queue(队列)
  • lpush + ltrim = Capped Collection(固定长度列表)
  • lpush + brpop = Message Queue(消息队列)

# 五、集合类型

  • 无序的
  • 无重复
  • 支持集合间的操作
API 描述 时间复杂度
增删
sadd key element 向集合 key 添加 element(如果 element 已经存在 添加失败) O(1)
srem key element 将集合 key 中的 element 移除掉 O(1)
查询
scard key 获取集合元素个数 O(1)
sismember key member 判断元素 member 是否在集合 key 中 O(1)
srandmember key count 从集合 key 中随机获取 count 个元素 O(1~n)
spop key 从集合 key 中随机弹出一个元素(从集合中删掉) O(1)
smembers key 获取集合 key 中所有元素 O(n)
集合间操作
sdiff key1 key2 差集 O(n)
sinter key1 key2 交集 O(n)
sunion key1 key2 并集 O(1)
sdiffstore/sinterstore/sunionstore destKey key1 key2 求集合间的差、交、并集,保存到集合 destKey 中 O(n)

# 六、有序集合类型

有序集合结构

image-20210603165541114

API 描述 时间复杂度
基本命令
zadd key score elemen 添加 score 和 element(可以多对) O(logN)
zrem key element 删除元素(可以是多个) O(1)
zscore key element 返回元素的分数 O(1)
zincrby key increScore element 增加或减少元素的分数 O(1)
范围操作
zrange key start end [WITHSCORES] 返回指定排名范围内的升序元素[分值] O(log(n) + m)
zrangebyscore key minScore maxScore [WITHSCORES] 返回指定分数范围内的升序元素[分值] O(log(n) + m)
zcount key minScore maxScore 返回有序集合内在指定分数范围内的个数 O(log(n) + m)
zremrangebyrank key start end 删除指定排名内的升序元素 O(log(n) + m)
zremrangebyscore key minScore maxScore 删除指定分数内的升序元素 O(log(n) + m)

其他命令:zrevrank、zrevrange、zrevrangebyscore、zinterstore、zunionstore

编辑 (opens new window)
上次更新: 2023/06/04, 12:34:19
第01章-初识Redis
第03章-Redis客户端

← 第01章-初识Redis 第03章-Redis客户端→

最近更新
01
第01章-RabbitMQ导学
02-10
02
第02章-入门RabbitMQ核心概念
02-10
03
第03章-RabbitMQ高级特性
02-10
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CodeAshen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式