程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 缓存数据库 - Redis

    • Redis - 介绍
    • Redis - 安装
    • Redis - 五大数据类型及API
      • 1. 五大数据类型
      • 2. 键(key)命令
        • 常用操作指令
        • 常用操作示例
      • 3. 字符串String
        • 常用操作指令
        • 单键单值示例
        • 自增自减示例
        • 多键多值示例
        • range范围示例
        • 键值条件示例
        • 存储对象示例
      • 4. 列表List
        • 常用操作指令
        • 常用操作示例
      • 5. 集合Set
        • 常用操作指令
        • 常用操作示例
      • 6. 哈希Hash
        • 常用操作指令
        • 常用操作示例
      • 7. 有序集合Zset
        • 常用操作指令
        • 常用操作示例
    • Redis - 新增三大数据类型
    • Redis - 配置文件
    • Redis - 发布和订阅
    • Redis - Java整合
    • Redis - 事务与锁
    • Redis - 两种持久化
    • Redis - 主从复制
    • Redis - 集群搭建
    • Redis - 缓存问题
    • Redis - 分布式锁
    • Redis - Spring Data Redis
  • 数据库
  • 缓存数据库 - Redis
scholar
2021-12-25
目录

Redis - 五大数据类型及API

笔记

Redis 常用的五大数据类型,这也是开发常用的数据类型,下面我们来学习每一个数据类型和其他的 API 命令。

  • 1. 五大数据类型
  • 2. 键(key)命令
    • 常用操作指令
    • 常用操作示例
  • 3. 字符串String
    • 常用操作指令
    • 单键单值示例
    • 自增自减示例
    • 多键多值示例
    • range范围示例
    • 键值条件示例
    • 存储对象示例
  • 4. 列表List
    • 常用操作指令
    • 常用操作示例
  • 5. 集合Set
    • 常用操作指令
    • 常用操作示例
  • 6. 哈希Hash
    • 常用操作指令
    • 常用操作示例
  • 7. 有序集合Zset
    • 常用操作指令
    • 常用操作示例

# 1. 五大数据类型

Redis支持多种数据类型,使其能够适用于各种不同场景的数据存储需求。以下是Redis支持的五种基本数据类型的详细介绍:

String(字符串类型)

  • 基本概念:String是Redis最基础的数据类型,一个键(key)对应一个值(value)。String类型可以存储任何形式的字符串,包括文本数据或二进制数据(例如,图片或序列化对象)。
  • 二进制安全:Redis的String类型是二进制安全的,意味着这里的“字符串”可以包含任何数据,例如零字节。
  • 大小限制:String类型的值最大可以存储512MB。

Hash(哈希类型)

  • 基本概念:Redis的Hash是键值对集合,类似于Java中的Map。Hash是由多个字段(field)和字段值(value)组成的映射表,适合用于存储对象。
  • 应用场景:Hash类型特别适用于存储对象,每个字段代表对象的一个属性,字段值存储属性的值。

List(列表类型)

  • 基本概念:List是按插入顺序排序的字符串列表,其底层实现是一个双向链表。
  • 特性:可以在列表的头部(左侧)或尾部(右侧)添加元素,支持双向的快速添加和删除操作。
  • 应用场景:适用于实现队列、栈等数据结构。

Set(集合类型)

  • 基本概念:Set是由字符串组成的无序集合,其底层实现基于HashTable,保证了内部元素的唯一性。
  • 特性:支持添加、删除、和成员测试等操作,并提供了集合间的运算,如交集、并集和差集。
  • 应用场景:适用于存储无序且唯一的数据集合。

Zset(有序集合类型)

  • 基本概念:Zset是由字符串成员和与之相关联的浮点数分数组成的有序集合,成员的添加和删除根据分数自动进行排序。
  • 特性:集合中的成员是唯一的,但分数可以重复。Redis通过分数实现成员的自动排序,支持范围查询和成员排名。
  • 应用场景:适合需要按一定顺序访问数据的场景,如排行榜系统。

每种数据类型都有其独特的属性和应用场景,选择合适的数据类型可以更高效地实现特定功能,提高Redis的使用效率。

# 2. 键(key)命令

# 常用操作指令

指令 含义
dbsize 查看当前数据库的 key 的数量
keys * 指令查看当前库所有 key
exists key 指令判断某个 key 是否存在
type key 指令查看 key 的类型是哪个
del key 指令删除指定的 key
unlink key 指令根据 value 选择非阻塞删除(先将 keys 从 keysapce 元数据中删除,真正的删除会在后续异步操作)
expire key time 指令给指定的 key 设置过期时间(time 以秒为单位),当 key 过期时(生存时间为 0 ),它会被自动删除
ttl key 指令查看 key 还有多少秒过期,-1 表示永不过期,-2 表示已过期
select num 指令选择数据库,num 代表从 0-16,默认是 0
flushdb 清空当前库
flushall 清空所有库

# 常用操作示例

查看当前数据库的 key 的数量

dbsize
1

keys * 指令查看当前库所有 key

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name kele
OK
127.0.0.1:6379> keys *
1) "name"
1
2
3
4
5
6

exists key 指令判断某个 key 是否存在

127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
1
2
3
4

type key 指令查看 key 的类型是哪个

127.0.0.1:6379> set name kele
OK
127.0.0.1:6379> get name
"kele"
127.0.0.1:6379> type name
string
1
2
3
4
5
6

del key 指令删除指定的 key

127.0.0.1:6379[1]> del name
(integer) 1
127.0.0.1:6379[1]> keys *
(empty array)
1
2
3
4

unlink key 指令根据 value 选择非阻塞删除(先将 keys 从 keysapce 元数据中删除,真正的删除会在后续异步操作)

127.0.0.1:6379[1]> unlink key name
(integer) 1
127.0.0.1:6379[1]> keys *
(empty array)
1
2
3
4

expire key time 指令给指定的 key 设置过期时间(time 以秒为单位),当 key 过期时(生存时间为 0 ),它会被自动删除

127.0.0.1:6379> set name kele
OK
127.0.0.1:6379> expire name 10
(integer) 1
1
2
3
4

ttl key 指令查看 key 还有多少秒过期,-1 表示永不过期,-2 表示已过期

127.0.0.1:6379> set name kele
OK
127.0.0.1:6379> expire name 10
(integer) 1
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
(empty list or set)
1
2
3
4
5
6
7
8
9
10
11
12

select num 指令选择数据库,num 代表从 0-16,默认是 0

select 7
1

flushdb 指令清空当前库

flushdb
1

flushall 指令清空所有库

flushall
1

# 3. 字符串String

image-20200623132104399

# 常用操作指令

指令 含义
set <key> <value> 添加键值对,如果 key 已经存在则覆盖 value
get <key> 查看对应键值
append <key> <value> 追加到原值的末尾
strlen <key> 获得值的长度
setnx <key> <value> 只有 key 不存在时,才加入该 key 的值
incr <key> 将 key 中储存的数字值增 1,只能对数字值操作,如果为空,新增值为 1
decr <key> 将 key 中储存的数字值减 1,只能对数字值操作,如果为空,新增值为 -1
incrby / decrby <步长> 将 key 中储存的数字值增减。自定义步长
mset <key1> <value> <key2> <value2> ...... 设置一个或者多个 key-value 键值对
mget <key1> <key2> ...... 获取一个或者多个 key-value 键值对
msetnx <key1> <value> <key2> <value2> ...... 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
getrange <key> <起始位置> <结束位置> 获得值的范围,类似 java 中的 substring
getrange <key> <起始位置> <value> 用 value 覆写所储存的字符串值,从 <起始位置> 开始(索引从 0 开始)
setrange <key> <位置> <newValue> 设置指定区间范围内的值
setex <key> <过期时间/秒> <value> 设置键值的同时,设置过期时间,单位秒
psetex <key> <过期时间/毫秒> <value> 设置键值的同时,设置过期时间,单位毫秒
getset <key> <value> 以新换旧,设置了新值同时获得旧值
set user:1 value(json数据) 存储对象

# 单键单值示例

  • set <key> <value> 指令添加键值对:

    set <key> <value>
    
    1

    注意,当 key 不存在,则将 key-value 存入数据库,如果存在,则覆盖原来 value

    示例:Redis 的分布式锁应用

    set lock locked nx ex 10
    
    1

    key 为 lock 的值 locked 在 10 秒内无法重新赋值,只有 10 秒后过期了,才能给 lock 赋值

  • get <key> 查看对应键值:

    get <key>
    
    1
  • append <key> <value> 追加到原值的末尾:

    append <key> <value>
    
    1
  • strlen <key> 获得值的长度:

    strlen <key>
    
    1
  • setnx <key> <value> 指令只有 key 不存在时,才加入该 key 的值:

    setnx <key> <value>
    
    1

案例:

127.0.0.1:6379> set key1 value1 # 设置值
OK
127.0.0.1:6379> get key1 # 获得key
"value1"
127.0.0.1:6379> del key1 # 删除key
(integer) 1
127.0.0.1:6379> keys * # 查看全部的key
(empty list or set)
127.0.0.1:6379> exists key1 # 确保 key1 不存在
(integer) 0
127.0.0.1:6379> append key1 "hello" # 对不存在的 key 进行 APPEND,等同于 SET key1 "hello"
(integer) 5 # 字符长度
127.0.0.1:6379> APPEND key1 "-2333" # 对已存在的字符串进行 APPEND
(integer) 10 # 长度从 5 个字符增加到 10 个字符
127.0.0.1:6379> get key1
"hello-2333"
127.0.0.1:6379> strlen key1 # # 获取字符串的长度
(integer) 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 自增自减示例

  • incr <key> 指令将 key 中储存的数字值增 1,只能对数字值操作,如果为空,新增值为 1:

    incr <key>
    
    1
  • decr <key> 指令将 key 中储存的数字值减 1,只能对数字值操作,如果为空,新增值为 -1:

    decr <key>
    
    1
  • incrby / decrby <步长> 指令将 key 中储存的数字值增减。自定义步长:

    incrby / decrby <步长>
    
    1

案例:

127.0.0.1:6379> set views 0 # 设置浏览量为 0
OK
127.0.0.1:6379> incr views # 浏览 + 1
(integer) 1
127.0.0.1:6379> incr views # 浏览 + 1
(integer) 2
127.0.0.1:6379> decr views # 浏览 - 1
(integer) 1

127.0.0.1:6379> incrby views 10 # +10
(integer) 11
127.0.0.1:6379> decrby views 10 # -10
(integer) 1
1
2
3
4
5
6
7
8
9
10
11
12
13

# 多键多值示例

  • mset <key1> <value> <key2> <value2> ...... 指令设置一个或者多个 key-value 键值对

    mset <key1> <value> <key2> <value2> ......
    
    1
  • mget <key1> <key2> ...... 指令获取一个或者多个 key-value 键值对

    mget <key1> <key2> ......
    
    1
  • msetnx <key1> <value> <key2> <value2> ...... 指令同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在

    msetnx <key1> <value> <key2> <value2> ......
    
    1

案例:

127.0.0.1:6379> mset k10 v10 k11 v11 k12 v12
OK
127.0.0.1:6379> keys *
1) "k12"
2) "k11"
3) "k10"

127.0.0.1:6379> mget k10 k11 k12 k13
1) "v10"
2) "v11"
3) "v12"
4) (nil)

127.0.0.1:6379> msetnx k10 v10 k15 v15 # 原子性操作
(integer) 0
127.0.0.1:6379> get key15
(nil)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# range范围示例

  • getrange <key> <起始位置> <结束位置> 指令获得值的范围,类似 Java 中的 substring

    getrange <key> <起始位置> <结束位置>
    
    1
  • setrange <key> <起始位置> <value> 指令用 value 覆写所储存的字符串值,从 <起始位置> 开始(索引从 0 开始)

    setrange <key> <起始位置> <value>
    
    1

案例:

127.0.0.1:6379> set key2 abcd123456 # 设置 key2 的值
OK
127.0.0.1:6379> getrange key2 0 -1 # 获得全部的值
"abcd123456"
127.0.0.1:6379> getrange key2 0 2 # 截取部分字符串
"abc"
1
2
3
4
5
6
  • setrange <key> <位置> <newValue> 指令设置指定区间范围内的值

    setrange <key> <位置> <newValue>
    
    1

案例:

127.0.0.1:6379> get key2
"abcd123456"
127.0.0.1:6379> setrange key2 1 xx # 替换值
(integer) 10
127.0.0.1:6379> get key2
"axxd123456"
1
2
3
4
5
6

从位置 1 开始,将值替换为 xx,因为 xx 长度为 2,所以替换到位置 3 就结束了。

# 键值条件示例

  • setex <key> <过期时间/秒> <value> 指令设置键值的同时,设置过期时间,单位秒

    setex <key> <过期时间/秒> <value>
    
    1
  • psetex <key> <过期时间/毫秒> <value> 指令设置键值的同时,设置过期时间,单位毫秒

    psetex <key> <过期时间/毫秒> <value>
    
    1

案例:

127.0.0.1:6379> setex key3 60 expire # 设置过期时间
OK
127.0.0.1:6379> ttl key3 # 查看剩余的时间
(integer) 55

127.0.0.1:6379> setnx mykey "redis" # 如果不存在就设置,成功返回1
(integer) 1
127.0.0.1:6379> setnx mykey "mongodb" # 如果值存在则不覆盖值,返回0
(integer) 0
127.0.0.1:6379> get mykey
"redis"
1
2
3
4
5
6
7
8
9
10
11
  • getset <key> <value> 指令以新换旧,设置了新值同时获得旧值

    getset <key> <value>
    
    1

案例:

127.0.0.1:6379> getset db mongodb # 没有旧值,返回 nil
(nil)
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379> getset db redis # 返回旧值 mongodb
"mongodb"
127.0.0.1:6379> get db
"redis"
1
2
3
4
5
6
7
8

# 存储对象示例

格式:

set user:1 value(json数据)
1

案例:

127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
1
2
3
4
5

案例:

java 中的 i++ 是否是原子操作?

不是。

当 i = 0 时,如果有两个线程分别对 i 进行 ++100 次,值是多少?

2-200。

# 4. 列表List

image-20200623161114380

List 的特点:单键多值。底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

# 常用操作指令

指令 含义
lpush/rpush <key> <value1> <value2> <value3> ... 从左边/右边插入一个或多个值,左右也就是首尾
lrange <key> <start> <stop> 按照索引下标获得元素(从左到右,先进后出)
lrange <key> 0 -1 如果 start 是 0,stop 是 -1,代表获取所有元素
lindex <key> <index> 按照索引下标获得元素(从左到右)(-1 代表最后一个,0 代表是第一个)
lpop/rpop <key> 从左边/右边吐出一个值。吐出后该值就不存在 key 中
rpoplpush <key1> <key2> 列表右边吐出一个值,插到列表左边,其中 key1 是 rpop 的 key,key2 是 lpush 的 key
llen <key> 获得列表长度
linsert <key> before/after <value> <newValue> 在元素某个值的前面/后面插入新值,如果 value 有多个,则插入最前面的那个
lrem <key> <n> <value> 从左边删除 n 个 value(从左到右),如果有多个一样的 lement,则删除列表最前面的的
lset <key> <index> <value> 将列表 key 下标为 index 的值替换成 value
ltrim key 对一个列表进行修剪(trim),只保留指定列表中区间内的元素,不在指定区间之内的元素都将被删除

# 常用操作示例

  • lpush/rpush <key> <value1> <value2> <value3> ... 指令从左边 / 右边插入一个或多个值,左右也就是首尾

    lpush/rpush <key> <value1> <value2> <value3> ...
    
    1

    例子:

    lpush k1 v1 v2 v3
    
    1
  • lrange <key> <start> <stop> 指令按照索引下标获得元素(从左到右,先进后出)

    lrange <key> <start> <stop>
    
    1
  • lrange <key> 0 -1 指令如果 start 是 0,stop 是 -1,代表获取所有元素

    lrange <key> 0 -1
    
    1

案例:

127.0.0.1:6379> lpush list "one"
(integer) 1
127.0.0.1:6379> lpush list "two"
(integer) 2
127.0.0.1:6379> rpush list "right"
(integer) 3

127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "right"
127.0.0.1:6379> lrange list 0 1
1) "two"
2) "one"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • lindex <key> <index> 指令按照索引下标获得元素(从左到右)(-1 代表最后一个,0 代表是第一个)

    lindex <key> <index>
    
    1

    例子:

    127.0.0.1:6379> lindex list 1
    (nil)
    127.0.0.1:6379> lindex list 0
    "one"
    127.0.0.1:6379> lindex list -1
    "one"
    
    1
    2
    3
    4
    5
    6
  • lpop/rpop <key> 指令从左边 / 右边吐出一个值。吐出后该值就不存在 key 中

    lpop/rpop <key>
    
    1

    例子:

    127.0.0.1:6379> lpop list
    "two"
    127.0.0.1:6379> rpop list
    "right"
    127.0.0.1:6379> lrange list 0 -1
    1) "one"
    
    1
    2
    3
    4
    5
    6
  • rpoplpush <key1> <key2> 指令列表右边吐出一个值,插到列表左边,其中 key1 是 rpop 的 key,key2 是 lpush 的 key

    rpoplpush <key1> <key2>
    
    1

    例子:

    127.0.0.1:6379> rpush mylist "hello"
    (integer) 1
    127.0.0.1:6379> rpush mylist "foo"
    (integer) 2
    127.0.0.1:6379> rpush mylist "bar"
    (integer) 3
    127.0.0.1:6379> rpoplpush mylist myotherlist
    "bar"
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "foo"
    127.0.0.1:6379> lrange myotherlist 0 -1
    1) "bar"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • llen <key> 指令获得列表长度

    llen <key>
    
    1

    例子:

    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> lpush list "one"
    (integer) 1
    127.0.0.1:6379> lpush list "two"
    (integer) 2
    127.0.0.1:6379> lpush list "three"
    (integer) 3
    127.0.0.1:6379> llen list # 返回列表的长度
    (integer) 3
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • linsert <key> before/after <value> <newValue> 指令在元素某个值的前面 / 后面插入新值,如果 value 有多个,则插入最前面的那个

    linsert <key> before/after <value> <newValue>
    
    1

    例子:

    127.0.0.1:6379> rpush mylist "Hello"
    (integer) 1
    127.0.0.1:6379> rpush mylist "world"
    (integer) 2
    127.0.0.1:6379> lrange mylist 0 -1
    1) "Hello"
    2) "world"
    
    127.0.0.1:6379> linsert mylist BEFORE "world" "There"
    (integer) 3
    127.0.0.1:6379> lrange mylist 0 -1
    1) "Hello"
    2) "There"
    3) "world"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  • lrem <key> <n> <value> 指令从左边删除 n 个 value(从左到右),如果有多个一样的 lement,则删除列表最前面的

    lrem <key> <n> <value>
    
    1

    例子:

    127.0.0.1:6379> lrem list 1 "two"
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "one"
    
    1
    2
    3
    4
    5
  • lset <key> <index> <value> 指令将列表 key 下标为 index 的值替换成 value

    lset <key> <index> <value>
    
    1

    例子:

    127.0.0.1:6379> exists list # 对空列表(key 不存在)进行 LSET
    (integer) 0
    127.0.0.1:6379> lset list 0 item # 报错
    (error) ERR no such key
    
    127.0.0.1:6379> lpush list "value1" # 对非空列表进行 LSET
    (integer) 1
    127.0.0.1:6379> lrange list 0 0
    1) "value1"
    127.0.0.1:6379> lset list 0 "new" # 更新值
    OK
    127.0.0.1:6379> lrange list 0 0
    1) "new"
    127.0.0.1:6379> lset list 1 "new" # index 超出范围报错
    (error) ERR index out of range
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  • ltrim key 指令对一个列表进行修剪(trim),只保留指定列表中区间内的元素,不在指定区间之内的元素都将被删除

    127.0.0.1:6379> rpush mylist "hello" "hello" "hello2" "hello3"
    (integer) 4
    127.0.0.1:6379> ltrim mylist 1 2
    OK
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "hello2"
    
    1
    2
    3
    4
    5
    6
    7

List 的数据结构为快速链表 quickList

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next。

Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

# 5. 集合Set

image-20200623193634316

集合 Set 特点:无序,不重复。底层其实是一个 value 为 null 的 hash 表,所以添加,删除,查找的复杂度都是 O(1)

# 常用操作指令

指令 含义
sadd <key> <value1> <value2> ... 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
smembers <key> 取出该集合的所有值
sismember <key> <value> 判断集合是否为含有该值,有 1,没有 0
scard <key> 返回该集合的元素个数
srem <key> <value1> <value2> ... 删除集合中的某个元素
spop <key> 随机从该集合中吐出一个值,key 里就没有该值了
srandmember <key> <n> 随机从该集合中取出 n 个值。不会从集合中删除
smove <key1> <key2> <value> 把集合中一个值从一个集合移动到另一个集合,其中 key1 为要获取的集合,key2 为放入的集合
sinter <key1> <key2> 返回两个集合的交集元素
sunion <key1> <key2> 返回两个集合的并集元素
sdiff <key1> <key2> 返回两个集合的差集元素(key1 中的,不包含 key2 中的)

# 常用操作示例

  • sadd <key> <value1> <value2> ... 指令将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略

    sadd <key> <value1> <value2> ...
    
    1

    例子:

    sadd k1 v1 v2 v3
    
    1
  • smembers <key> 指令取出该集合的所有值

    smembers <key>
    
    1
  • sismember <key> <value> 指令判断集合是否为含有该值,有 1,没有 0

    sismember <key> <value>
    
    1

案例:

127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "kele"
(integer) 1
127.0.0.1:6379> sadd myset "kele" # 重复值不插入 返回 0
(integer) 0
127.0.0.1:6379> smembers myset # 查看集合中所有成员
1) "kele"
2) "hello"
127.0.0.1:6379> sismember myset "hello" # 是否是此集合的成员 是 1
(integer) 1
127.0.0.1:6379> sismember myset "world"
(integer) 0
1
2
3
4
5
6
7
8
9
10
11
12
13
  • scard <key> 指令返回该集合的元素个数

    scard <key>
    
    1

    例子:

    127.0.0.1:6379> scard myset
    (integer) 2
    
    1
    2
  • srem <key> <value1> <value2> ... 指令删除集合中的某个元素

    srem <key> <value1> <value2> ...
    
    1

    例子:

    127.0.0.1:6379> srem myset "kele"
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) "hello"
    
    1
    2
    3
    4
  • spop <key> 指令随机从该集合中吐出一个值,key 里就没有该值了

    spop <key>
    
    1

    例子:

    127.0.0.1:6379> smembers myset
    1) "kele"
    2) "world"
    3) "hello"
    127.0.0.1:6379> spop myset
    "world"
    127.0.0.1:6379> spop myset 2
    1) "kele"
    2) "hello"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • srandmember <key> <n> 指令随机从该集合中取出 n 个值。不会从集合中删除

    srandmember <key> <n>
    
    1

    例子:

    127.0.0.1:6379> smembers myset
    1) "kele"
    2) "world"
    3) "hello"
    127.0.0.1:6379> srandmember myset
    "hello"
    127.0.0.1:6379> srandmember myset 2
    1) "world"
    2) "kele"
    127.0.0.1:6379> srandmember myset 2
    1) "kele"
    2) "hello"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • smove <key1> <key2> <value> 指令把集合中一个值从一个集合移动到另一个集合,其中 key1 为要获取的集合,key2 为放入的集合

    smove <key1> <key2> <value>
    
    1

    例子:

    127.0.0.1:6379> sadd myset "hello" # myset 添加元素
    (integer) 1
    127.0.0.1:6379> sadd myset "world"
    (integer) 1
    127.0.0.1:6379> sadd myset "kele"
    (integer) 1
    127.0.0.1:6379> sadd myset2 "set2" # myset2 添加元素
    (integer) 1
    127.0.0.1:6379> smove myset myset2 "kele"
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) "world"
    2) "hello"
    127.0.0.1:6379> smembers myset2
    1) "kele"
    2) "set2"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • sinter <key1> <key2> 指令返回两个集合的交集元素

    sinter <key1> <key2>
    
    1
  • sunion <key1> <key2> 指令返回两个集合的并集元素

    sunion <key1> <key2>
    
    1
  • sdiff <key1> <key2> 指令返回两个集合的差集元素(key1 中的,不包含 key2 中的)

    sdiff <key1> <key2>
    
    1

案例:

127.0.0.1:6379> sadd key1 "a" # key1
(integer) 1
127.0.0.1:6379> sadd key1 "b"
(integer) 1
127.0.0.1:6379> sadd key1 "c"
(integer) 1
127.0.0.1:6379> sadd key2 "c" # key2
(integer) 1
127.0.0.1:6379> sadd key2 "d"
(integer) 1
127.0.0.1:6379> sadd key2 "e"
(integer) 1
127.0.0.1:6379> sdiff key1 key2 # 差集
1) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 # 交集
1) "c"
127.0.0.1:6379> sunion key1 key2 # 并集
1) "a"
2) "b"
3) "c"
4) "e"
5) "d"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在微博中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

# 6. 哈希Hash

image-20200623200348408

特点:键值对集合,也是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

类似与 Java 的 Map<String, Map<Object,Object>>,即双 Map。

通过 key(用户 ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题

# 常用操作指令

指令 含义
hset <key> <field1> <value> <field2> <value> ... 给集合 key 的 filed 键赋值 value,批量也可以,4.0 之前是 hmset,现在 hset 也可以批量添加
hget <key> <field> 从 key 集合取出 value
hexists <key> <field> 查看哈希表 key 中,给定域 field 是否存在
hkeys <key> 列出该 hash 集合的所有 field
hvals <key> 列出该 hash 集合的所有 value
hincrby <key> <field> <increment> 为哈希表 key 中的域 field 的值加上增量
hsetnx <key> <filed> <value> 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

# 常用操作示例

  • hset <key> <field1> <value> <field2> <value> ... 指令给集合 key 的 filed 键赋值 value,批量也可以,4.0 之前是 hmset,现在 hset 也可以批量添加

    hset <key> <field1> <value> <field2> <value> ...
    
    1

    例子:

    hset user:1000 name kele age 18 gender boy
    
    1
  • hget <key> <field> 指令从 key 集合取出 value

    hget <key> <field>
    
    1

    例子:

    hget user:1000 name
    
    1
  • hexists <key> <field> 指令查看哈希表 key 中,给定域 field 是否存在

    hexists <key> <field>
    
    1

    例子:

    127.0.0.1:6379> hexists myhash field1
    (integer) 1
    127.0.0.1:6379> hexists myhash field3
    (integer) 0
    
    1
    2
    3
    4
  • hkeys <key> 指令列出该 hash 集合的所有 field

    hkeys <key>
    
    1
  • hvals <key> 指令列出该 hash 集合的所有 value

    hvals <key>
    
    1

    例子:

    127.0.0.1:6379> hkeys myhash
    1) "field2"
    2) "field1"
    127.0.0.1:6379> hvals myhash
    1) "World"
    2) "Hello"
    
    1
    2
    3
    4
    5
    6
  • hincrby <key> <field> <increment> 指令为哈希表 key 中的域 field 的值加上增量

    hincrby <key> <field> <increment>
    
    1

    例子:

    127.0.0.1:6379> hset myhash field 5
    (integer) 1
    127.0.0.1:6379> hincrby myhash field 1
    (integer) 6
    127.0.0.1:6379> hincrby myhash field -1
    (integer) 5
    127.0.0.1:6379> hincrby myhash field -10
    (integer) -5
    
    1
    2
    3
    4
    5
    6
    7
    8
  • hsetnx <key> <filed> <value> 指令将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

    hsetnx <key> <filed> <value>
    
    1

    例子:

    127.0.0.1:6379> hsetnx myhash field1 "hello"
    (integer) 1 	# 设置成功,返回 1 。
    127.0.0.1:6379> hsetnx myhash field1 "world"
    (integer) 0 	# 如果给定字段已经存在,返回 0
    127.0.0.1:6379> hget myhash field1
    "hello"
    
    1
    2
    3
    4
    5
    6

# 7. 有序集合Zset

image-20200623194903967

有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复。

# 常用操作指令

指令 含义
zadd <key> <score1> <value1> <score2> <value2> ... 将一个或多个 member 元素及其 score 值加入到有序集 key 当中
zrange <key> <start> <stop> [withscores] 返回有序集 key 中,下标在 star t和 stop 之间的元素,带 WITHSCORES,可以让分数一起和值(从小到大)返回到结果集
zrevrange <key> <start> <stop> [withscores] 同上,改为从大到小排列
zrangebyscore <key> <min> <max> [withscores] [limit offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。 有序集成员按 score 值递增(从小到大)次序排列
zrevrangebyscore <key> <min> <max> [withscores] [limit offset count] 同上,改为从大到小排列
zincrby <key> <increment> <value> 为元素的 score 加上增量
zrem <key> <value> 删除该集合下,指定值的元素
zcount <key> <min> <max> 统计该集合,分数区间内的元素个数
zrank <key> <value> 返回该值在集合中的排名,从 0 开始
zrevrank <key> <value> 返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序

# 常用操作示例

  • zadd <key> <score1> <value1> <score2> <value2> ... 指令将一个或多个 member 元素及其 score 值加入到有序集 key 当中

    zadd <key> <score1> <value1> <score2> <value2> ...
    
    1

    例如:

    zadd topn 1000 java 800 c++ 600 php 400 js
    
    1
  • zrange <key> <start> <stop> [withscores] 指令返回有序集 key 中,下标在 start 和 stop 之间的元素

    带 WITHSCORES,可以让分数一起和值返回到结果集

    zrange <key> <start> <stop> [withscores]
    
    1

    例如:(0 和 -1 代表查询所有)

    127.0.0.1:6379> zrange topn 0 -1 withscores
    1) "java" 1000
    2) "c++" 800
    3) "php" 600
    4) "js" 400
    
    1
    2
    3
    4
    5
    • zrevrange <key> <start> <stop> [withscores] 指令同上,改为从大到小排列
    zrevrange <key> <start> <stop> [withscores]
    
    1
  • zrangebyscore <key> <min> <max> [withscores] [limit offset count] 指令返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max)的成员。 有序集成员按 score 值递增(从小到大)次序排列

    zrangebyscore <key> <min> <max> [withscores] [limit offset count]
    
    1
    • zrevrangebyscore <key> <min> <max> [withscores] [limit offset count] 指令同上,改为从大到小排列

      zrevrangebyscore <key> <min> <max> [withscores] [limit offset count]
      
      1

    例子:

    127.0.0.1:6379> zadd salary 2500 xiaoming
    (integer) 1
    127.0.0.1:6379> zadd salary 5000 xiaohong
    (integer) 1
    127.0.0.1:6379> zadd salary 500 kele
    (integer) 1
    
    # Inf 无穷大量 +∞,同样地,-∞ 可以表示为 -Inf。
    127.0.0.1:6379> zrangebyscore salary -inf +inf # 显示整个有序集
    1) "kele"
    2) "xiaoming"
    3) "xiaohong"
    127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 递增排列
    1) "kele"
    2) "500"
    3) "xiaoming"
    4) "2500"
    5) "xiaohong"
    6) "5000"
    127.0.0.1:6379> zrevrange salary 0 -1 withscores # 递减排列
    1) "xiaohong"
    2) "5000"
    3) "xiaoming"
    4) "2500"
    5) "kele"
    6) "500"
    # 显示工资 <= 2500 的所有成员
    127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores 
    1) "kele"
    2) "500"
    3) "xiaoming"
    4) "2500"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
  • zincrby <key> <increment> <value> 指令为元素的 score 加上增量

    zincrby <key> <increment> <value>
    
    1
  • zrem <key> <value> 指令删除该集合下,指定值的元素

    zrem <key> <value>
    
    1

    例子:

    127.0.0.1:6379> zrange salary 0 -1
    1) "kele"
    2) "xiaoming"
    3) "xiaohong"
    127.0.0.1:6379> zrem salary kele
    (integer) 1
    127.0.0.1:6379> zrange salary 0 -1
    1) "xiaoming"
    2) "xiaohong"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • zcount <key> <min> <max> 指令统计该集合,分数区间内的元素个数

    zcount <key> <min> <max>
    
    1

    例子:

    127.0.0.1:6379> zadd myset 1 "hello"
    (integer) 1
    127.0.0.1:6379> zadd myset 2 "world" 3 "kele"
    (integer) 2
    127.0.0.1:6379> zcount myset 1 3
    (integer) 3
    127.0.0.1:6379> zcount myset 1 2
    (integer) 2
    
    1
    2
    3
    4
    5
    6
    7
    8
  • zrank <key> <value> 指令返回该值在集合中的排名,从 0 开始

    zrank <key> <value>
    
    1

    例子:

    127.0.0.1:6379> zadd salary 2500 xiaoming
    (integer) 1
    127.0.0.1:6379> zadd salary 5000 xiaohong
    (integer) 1
    127.0.0.1:6379> zadd salary 500 kele
    (integer) 1
    127.0.0.1:6379> zrange salary 0 -1 withscores # 显示所有成员及其 score 值
    1) "kele"
    2) "500"
    3) "xiaoming"
    4) "2500"
    5) "xiaohong"
    6) "5000"
    127.0.0.1:6379> zrank salary kele # 显示 kele 的薪水排名,最少
    (integer) 0
    127.0.0.1:6379> zrank salary kele # 显示 xiaohong 的薪水排名,第三
    (integer) 2
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  • zrevrank <key> <value> 指令返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序

    zrevrank <key> <value>
    
    1

    例子:

    127.0.0.1:6379> zrevrank salary kele
    (integer) 2
    127.0.0.1:6379> zrevrank salary kele
    (integer) 0
    
    1
    2
    3
    4

案例:利用 zset 实现一个文章访问量的排行榜

zadd topn 1000 java 800 c++ 600 php 400 js  # 添加文章以及评分
zrevrange topn 0 9 withscores # 评分从大到小查询
1
2

SortedSet(zset)是 Redis 提供的一个非常特别的数据结构,一方面它等价于 Java 的数据结构 Map,可以给每一个元素 value 赋予一个权重 score,另 一方面它又类似于 TreeSet,内部的元素会按照权重 score 进行排序,可以得到每个元素的名次,还可以通过 score 的范围来获取元素的列表。

zset 底层使用了两个数据结构:

  • hash,hash 的作用就是关联元素 value 和权重 score,保障元素 value 的唯一性,可以通过元素 value 找到相应的 score 值。

  • 跳跃表,跳跃表的目的在于给元素 value 排序,根据 score 的范围获取元素列表。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Redis - 安装
Redis - 新增三大数据类型

← Redis - 安装 Redis - 新增三大数据类型→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式