Redis —— 基本数据类型 String Hash List (二)

前一篇入口:redis 入门-1

1. string

字符串是 redis 中最基础的数据类型。

(1)redis 中所有键都是 string 类型,其它几种数据结构均在字符串类似基础上构建

(2)字符串类型的值可以是 字符串(一般字符串或JSON,XML等格式的字符串),数字(int 或 float),二进制流数据(如图片,音频,视频等;但是一个字符串最大不超 512MB)

(3)redis 按二进制流保存 字符串,故不涉及字符集编码问题,传入什么编码,就存什么编码

1.1 基本命令

1.1.1 set

设置 key 的 value,如已存在,则覆盖。之前在该 key 上的 ttl 也失效。

返回值 OK:成功, nil:失败
时间复杂度:O(1)

bash 复制代码
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

ex : seconds 秒为单位的过期时间,
px : milliseconds 毫米单位过期时间,
nx : 不存在则设置,反之不执行,
xx: 存在则设置,反之不执行

setnxsetexpsetex 等带要求的 set 可以由这些替代

1.1.2 get

获取key对应的 value,

返回值: key存在返对应value,key不存则返 nil
时间复杂度:O(1)

bash 复制代码
 GET key

1.1.3 mget

一次得多个 value,

返回值: key存在返对应value,key不存或不是string类型则返 nil
时间复杂度:O(N) N 是 key 数量

bash 复制代码
MGET key [key ...]

1.1.4 mset

一次设置多个 key 的值,

返回值:OK
时间复杂度:O(N) N 是 key 数量

bash 复制代码
MSET key value [key value ...]

相较于多个key 多次get/set 要经历多次网络传输,

而 mset/mget 之经历一次网络传输。

一定范围内(无节制的话会导致,redis堵塞)用 mset/ mget 批量处理,效率更高。

1.1.5 incr

value 是整型则加一 ,不是整型或超出64位有符号整型 则报错,不存则创建(初始值为 0),

返回最终值
时间复杂度:O(1)

bash 复制代码
INCR key

1.1.6 incrby

value 是整型则加指定数值 ,不是整型或超出64位有符号整型 则报错,不存则创建(初始值为 0),

返回最终值
时间复杂度:O(1)

bash 复制代码
INCRBY key decrement

1.1.7 decr

value 是整型则减一,不是整型或超出64位有符号整型则报错,不存则创建(初始值为 0);

返回最终值
时间复杂度:O(1)

bash 复制代码
DECR key

1.1.8 decrby

value 是整型则减指定数值,不是整型或超出64位有符号整型则报错,不存则创建(初始值为 0);

返回最终值
时间复杂度:O(1)

bash 复制代码
DECRBY key decrement

1.1.9 incrbyfloat

value 是浮点数则加指定值 ,不是string 或 不是浮点则报错,不存则创建(初始值为 0),

返最终值。

加的这个值允许用科学计数法表示
时间复杂度:O(1)

bash 复制代码
INCRBYFLOAT key increment

1.1.10 append

key存在则追加,不存则创建,返回字符串总长。
时间复杂度:O(1),追加的字符串⼀般较短, 可以视为 O(1)。

bash 复制代码
APPEND KEY VALUE

1.1.11 getrange

bash 复制代码
GETRANGE key start end

取子串,左闭右闭,下标从 0 算。可以用负数表示倒着来,eg:-1 即倒数第一个字符。 如果超出 string 长度则自动取正确的值,返回子串
时间复杂度:O(N),N 为 [start, end] 区间的长度。由于 string 通常较短,可以视为是 O(1)

1.1.12 setrange

bash 复制代码
SETRANGE key offset value

覆盖子串,从指定的偏移开始,下标从 0 开始计算
时间复杂度:O(N),N 为 value的长度。由于 value 通常较短,可以视为是 O(1)

1.1.13 strlen

bash 复制代码
STRLEN key

得字符串长度,不是 string 则报错
时间复杂度:O(1)

1.2 内部编码

字符串内部编码:

  • int:8字节长整型
  • embstr:小于等于39字节 字符串
  • raw :大于39字节字符串
    redis 会根据当前值的类型和长度动态选择用哪种编码

1.3 常见使用场景

  • 缓存
    用 string 类型存储信息,当作缓存。
  • 计数
    例如:视频播放次数可以用 redis 实现,视频放一次,对应播放数 +1
  • 共享会话
    用户的请求会经负载均衡后,会均匀发给各个服务器,这存在上一请求刚在一个服务器上保存了session信息(如登录信息),下一个请求到了另一台上,没有用户信息要重新登录的问题。
    可以用 redis 集中管理 session信息,服务器从 redis 中查询,更新 session信息。
  • 手机验证码
    redis设置过期时间,记录发送次数。

2. Hash

redis 中 hash 是 key-value 中的 value 又是一个键值对结构。

可以将 key 看作是 哈希表的表名,value 是哈希表的内容。

由于 redis 本身使用键值对存储数据(key-value),为了作区分,hash 类型中的映射关系为 field-value

2.1 基本命令

2.1.1 HSET & HGET

hset 设置hash中字段field 的 值value

返回值为添加的字段的个数
时间复杂度:插入一组 field 为 O(1),插入 N 组 field 为 O(N)

bash 复制代码
HSET key field value [field value ...]

hget 拿hash中 字段的值

返回字段值 或 nil
时间复杂度: O(1)

bash 复制代码
HGET key field
shell 复制代码
127.0.0.1:6379> HSET myhash field1 "hello"
1
127.0.0.1:6379> HGET myhash field1
hello

2.1.2 HEXISTS & HDEL

bash 复制代码
HEXISTS key field

HDEL key field [field ...]

hexists 判断hash中是否存在指定字段 返回 1:存在,0:不存
时间复杂度: O(1)

hdel 删除hash中的字段,返回删除的字段个数
时间复杂度: O(N),N为元素个数

bash 复制代码
127.0.0.1:6379> HEXISTS myhash field1
1
127.0.0.1:6379> HEXISTS myhash field2
0
127.0.0.1:6379> HSET myhash field2 "world"
1
127.0.0.1:6379> HGET myhash field2
world
127.0.0.1:6379> HDEL myhash field2
1

2.1.3 HKEYS & HVALS

bash 复制代码
HKEYS key

HVALS key

hkeys 获取hash中所有字段 返回字段列表
时间复杂度: O(N),N为field个数

hvals 获取hash中所有字段的值,返回所有的值
时间复杂度: O(N),N为field个数

bash 复制代码
127.0.0.1:6379> HSET myhash field2 "world"
1
127.0.0.1:6379> HKEYS myhash
field1
field2
127.0.0.1:6379> HVALS myhash
hello
world

2.1.4 HGETALL

bash 复制代码
HGETALL key

hgetall 获取hash中所有字段及其对应的值 返回字段和对应值
时间复杂度: O(N),N为field个数

bash 复制代码
127.0.0.1:6379> HGETALL myhash
field1
hello
field2
world

2.1.5 HMGET

bash 复制代码
HMGET key field [field ...]

HMGET 一次得多个字段的值 返回 值或nil
时间复杂度: O(N),N为元素个数

bash 复制代码
127.0.0.1:6379> HMGET myhash field1 field2
hello
world

2.1.6 HLEN

bash 复制代码
HLEN key

HLEN hash中字段个数 返字段个数
时间复杂度: O(1)

bash 复制代码
127.0.0.1:6379> HLEN myhash
2

2.1.7 HSETNX

bash 复制代码
HSETNX key field value

HSETNX 不存,则设置对应字段和值 返1:成功,0:失败
时间复杂度: O(1)

bash 复制代码
127.0.0.1:6379> HSETNX myhash field3 "你好"
1
127.0.0.1:6379> HSETNX myhash field3  20
0

2.1.8 HINCRBY

bash 复制代码
HINCRBY key field increment

HINCRBY hash中字段对应值加指定数值 返最终值
时间复杂度: O(1)

bash 复制代码
127.0.0.1:6379> HSET myhash field3  20
0
127.0.0.1:6379> HINCRBY myhash field3 16
36

2.1.9 HINCRBYFLOAT

bash 复制代码
HINCRBYFLOAT key field increment

HINCRBYFLOAT hash中字段对应值加指定浮点数 返最终值
时间复杂度: O(1)

bash 复制代码
127.0.0.1:6379> hget myhash field4
20
127.0.0.1:6379> HINCRBYFLOAT myhash field4 16.0
36
127.0.0.1:6379> HINCRBYFLOAT myhash field4 -0.3
35.7

2.2 内部编码

hash 内部编码有两种:

  • ziplist(压缩链表):哈希类型元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),且所有值小于 hash-max-ziplist-value 配置(默认 64个字节)时用 ziplist。ziplist 多元素连续存储的实现结构更紧凑,较 hashtable 省内存
  • hashtable(哈希表):不满足ziplist时,用 hashtable 作底层实现,因此时 ziplist 读写效率会下降,而 hashtable 的读写时复为 O(1)

2.3 使用场景

  • 保存用户信息
    相比于 JSON格式的字符串缓存用户信息,hash 类型更直观,且在更新上更灵活。

哈希类型和关系型数据库的不同

  • 哈希类型时稀疏的,关库是完全结构化的,eg:hash 类型每个键可有不同的field,而关库加了新列,其他行都有为其设值
  • 关库可做复杂的关系查询,而 redis 模拟关系型复杂查询,如:联表查询,聚合查询等基本不可能,维护成本高
  • 缓存方式对比
  1. 直接存字符串,每个属性一个键
bash 复制代码
set user:1:name James
set user:1:age 23
set user:1:city Beijing

优:简单,针对单个属性的变更灵活

缺:占用过多键,内存占用大;同时信息分散,内聚性低;基本没有实用性

  1. 序列化字符串类型,如 JSON 格式
bash 复制代码
set user:1 经过序列化后的⽤⼾对象字符串

优:针对整体操作的信息合适,编程简单;序列化方案选择合适,内存利用率高

缺:序列化和反序列化有一定开销,针对单个属性的操作不灵活

  1. 哈希类型
bash 复制代码
mset user:1 name James age 23 city Beijing

优:简单,直观,灵活,特别是针对信息的局部变更或获取

缺:要控制哈希在 ziplist 和 hashtable 内部编码间的转换,可能造成内存消耗大

3. List

列表类型用于存储多个有序字符串,列表中每个字符串称为元素,最多可存 2^32 - 1 个元素。

list 中元素有序,可通过下标获取某一元素或某个范围的元素列表。

下标:

  • 从左到右:0,1,2,......
  • 从右向左:-1,-2,-3,......

3.1 基本命令

3.1.1 LPUSH

bash 复制代码
LPUSH key element [element ...]

将一个/多个元素从左侧插入 list

返:插入后list 长度

bash 复制代码
127.0.0.1:6379> LPUSH mylist "world"
1
127.0.0.1:6379> LPUSH mylist "hellow"
2
127.0.0.1:6379> LRANGE mylist 0 -1
hellow
world

3.1.2 LPUSHX

bash 复制代码
 LPUSHX key element [element ...]

可以存在则从左插入list,不存在,则直接返回

返:插入后的长度

bash 复制代码
127.0.0.1:6379> LPUSHX mylist2 "HELLO"
0
127.0.0.1:6379> LPUSHX mylist "888888"
5

3.1.3 RPUSH,RPUSHX

同 LPUSH,RPUSHX,但右侧插入。

3.1.4 LRANG

bash 复制代码
LRANGE key start stop

获得指定范围元素,左闭右闭。

返:指定区间元素

bash 复制代码
127.0.0.1:6379> LRANGE mylist 0 -1
HELLOW
WORLD
and
hellow
world

3.1.5 LPOP/RPOP

bash 复制代码
 LPOP key

从list左/右侧侧取出元素(头/尾删)

返:取出的元素 或 nil

bash 复制代码
127.0.0.1:6379> LPOP mylist
888888

3.1.6 LINDEX

bash 复制代码
LINDEX key index

获取从左数地 index 位置元素

返:元素 或 nil

bash 复制代码
127.0.0.1:6379> LINDEX mylist 2
hellow

3.1.7 LINSERT

bash 复制代码
LINSERT key <BEFORE | AFTER> pivot element

指定位置插入元素

返:插入和长度

bash 复制代码
127.0.0.1:6379> LRANGE mylist 0 -1
HELLOW
WORLD
hellow
world
127.0.0.1:6379> LINSERT mylist BEFORE "hellow" "and"
5
127.0.0.1:6379> LRANGE mylist 0 -1
HELLOW
WORLD
and
hellow
world

3.1.8 LLEN

bash 复制代码
LLEN key

获取 list 长度

返:长度

bash 复制代码
127.0.0.1:6379> LLEN mylist
5

3.1.9 BLPOP/BRPOP

bash 复制代码
BLPOP key [key ...] timeout

LPOP 和 RPOP 的阻塞版本

list 有元素时,阻塞与非阻塞表现一致;

没有元素时,非阻塞直接返 nil,而阻塞则根据 timeout (单位为秒),阻塞一段时间,期间有元素存入,则取出,若到了 timeout,还没有则返回 nil。

阻塞期间,redis 可以执行其他命令,但执行该命令的客户端会表现为阻塞状态

如果多个客户端同时都对一个 key 执行 阻塞pop,先执行的先得元素。

bash 复制代码
127.0.0.1:6379> EXISTS mylist mylist2
1
127.0.0.1:6379> BLPOP mylist mylist2 10
mylist
HELLOW

3.2 内部编码

  • ziplist(压缩链表) :列表元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),且所有值小于 hash-max-ziplist-value 配置(默认 64个字节)时用 ziplist。ziplist 多元素连续存储的实现结构更紧凑,省内存
  • linkedlist(链表):不满足ziplist要求,则用 linkedlist

3.3 使用场景

  • 消息队列
    lpush + brpop 实现经典的阻塞式生产者-消费者模型队列,⽣产者客户端 lpush 从左侧插入元素,多个消费者客户端 brpop 阻塞式地从队列中取元素。
  • 微博 Timeline
  • 同侧存取:栈;异侧:队列
相关推荐
小毅&Nora9 小时前
【后端】【工具】Redis Lua脚本漏洞深度解析:从CVE-2022-0543到Redis 7.x的全面防御指南
redis·安全·lua
Thexhy10 小时前
CentOS7安装Redis全攻略
linux·经验分享·redis·学习
cui_win10 小时前
Redis 生产环境命令管控规范
数据库·redis·缓存
小坏讲微服务11 小时前
Spring Boot4.0 集成 Redis 实现看门狗 Lua 脚本分布式锁完整使用
java·spring boot·redis·分布式·后端·lua
为什么要做囚徒11 小时前
并发系列(一):深入理解信号量(含 Redis 分布式信号量)
redis·分布式·多线程·并发编程·信号量
嘻哈baby1 天前
Redis高可用部署与集群管理实战
数据库·redis·bootstrap
Java爱好狂.1 天前
Java面试Redis核心知识点整理!
java·数据库·redis·分布式锁·java面试·后端开发·java八股文
阿杆1 天前
如何在 Spring Boot 中接入 Amazon ElastiCache
java·数据库·redis
此生只爱蛋1 天前
【Redis】String 字符串
java·数据库·redis