Redis - 2 ( 13000 字 Redis 入门级教程 )

一: String 字符串

字符串是 Redis 中最基础的数据类型,它具有以下特点:所有键的类型都是字符串,其它数据结构(如列表和集合)的元素也基于字符串,因此字符串类型是理解其它数据结构的基础。字符串的值可以是普通字符串(如 JSON 或 XML 格式)、数字(整型或浮点型)、或二进制流数据(如图片、音频、视频),但单个字符串的最大值不得超过 512 MB。由于 Redis 内部以二进制流的形式存储字符串,因此不处理字符集编码问题,客户端使用什么字符集编码传入数据,Redis 就以相同的编码方式存储。

在这里插入图片描述

1.1 常见命令

1.1.1 SET

SET 命令用于将字符串类型的值设置到指定的 key 中。如果 key 已存在,无论原有的数据类型是什么都会被覆盖,同时清除该 key 的 TTL。返回值为 OK 表示设置成功;如果使用了 NX 或 XX 参数但条件不满足,SET 将不会执行,返回 (nil)。

SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
参数描述
EX seconds使用秒作为单位设置 key 的过期时间。
PX milliseconds使用毫秒作为单位设置 key 的过期时间。
NX仅在 key 不存在时才执行设置操作,如果 key 已存在,则不执行设置。
XX仅在 key 存在时才执行设置操作,如果 key 不存在,则不执行设置。
|表示二选一,即只能在 EX seconds 和 PX milliseconds 之间选择一个,或者在 NX 和 XX 之间选择一个。
[ ]表示该部分为可选参数,可以根据需要选择性添加,不是必须的。
# 情况一:
EXISTS mykey
(integer) 0

SET mykey "Hello"
OK

GET mykey
"Hello"

# 情况二:
SET mykey "World" NX
(nil)

DEL mykey
(integer) 1

EXISTS mykey
(integer) 0

SET mykey "World" XX
(nil)

GET mykey
(nil)

# 情况三:
SET mykey "World" NX
OK

GET mykey
"World"

SET mykey "Will expire in 10s" EX 10
OK

GET mykey
"Will expire in 10s"

GET mykey
(nil)

1.1.2 GET

GET 命令用于获取指定 key 的值。如果 key 存在且值为字符串类型,则返回对应的 value;如果 key 不存在,则返回 nil;如果 key 的值不是字符串类型,则会返回错误。

redis> GET nonexisting
(nil)

redis> SET mykey "Hello"
"OK"

redis> GET mykey
"Hello"

redis> DEL mykey
(integer) 1

redis> EXISTS mykey
(integer) 0

redis> HSET mykey name Bob
(integer) 1

redis> GET mykey
(error) WRONGTYPE Operation against a key holding the wrong kind of value

1.1.3 MGET

MGET 命令用于一次性获取多个 key 的值。对于不存在的 key 或数据类型不是字符串的 key,返回结果为 nil。返回值是对应 key 的 value 列表。

MGET key [key ...]
redis> SET key1 "Hello"
"OK"

redis> SET key2 "World"
"OK"

redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)

1.1.4 MSET

MSET 命令用于一次性设置多个 key 的值,返回值始终为 OK。

MSET key value [key value ...]
redis> MSET key1 "Hello" key2 "World"
"OK"

redis> GET key1
"Hello"

redis> GET key2
"World"

1.1.5 多次 get vs 单次 mget

使用 MGET 和 MSET 命令可以有效减少网络传输时间从而提升性能。通过批量操作能够显著提高业务处理效率,但需要注意,批量操作的键数量不宜过多,否则可能导致单条命令执行时间过长,引发 Redis 阻塞问题。

在这里插入图片描述

在这里插入图片描述

1.1.6 SETNX

SETNX 命令用于在 key 不存在时设置 key-value 对。返回值:1 表示设置成功,0 表示未设置(因 key 已存在)。

SETNX key value
redis> SETNX mykey "Hello"
(integer) 1

redis> SETNX mykey "World"
(integer) 0

redis> GET mykey
"Hello"

在这里插入图片描述

1.1.7 INCR

INCR 命令用于将 key 对应的字符串形式的数字加一。如果 key 不存在,则默认将其值视为 0 再进行加一操作。如果 key 的值不是整型字符串或超出 64 位有符号整型范围,则会报错。返回值为加一后的整数值。

INCR key
redis> EXISTS mykey
(integer) 0

redis> INCR mykey
(integer) 1

redis> SET mykey "10"
"OK"

redis> INCR mykey
(integer) 11

redis> SET mykey "234293482390480948029348230948"
"OK"

redis> INCR mykey
(error) value is not an integer or out of range

redis> SET mykey 'not a number'
"OK"

redis> INCR mykey
(error) value is not an integer or out of range

1.1.8 INCRBY

INCRBY 命令用于将 key 对应的字符串形式的数字加上指定的值。如果 key 不存在,则默认将其值视为 0 再进行加法操作。如果 key 的值不是整型字符串或超出 64 位有符号整型范围,则会报错。返回值为加法运算后的整数值。

INCRBY key decrement
EXISTS mykey
(integer) 0

INCRBY mykey 3
(integer) 3

SET mykey "10"
"OK"

INCRBY mykey 3
(integer) 13

INCRBY mykey "not a number"
(error) ERR value is not an integer or out of range

SET mykey "234293482390480948029348230948"
"OK"

INCRBY mykey 3
(error) value is not an integer or out of range

SET mykey "not a number"
"OK"

INCRBY mykey 3
(error) value is not an integer or out of range

1.1.9 DECR

DECR 命令用于将 key 对应的字符串形式的数字减一。如果 key 不存在,则默认将其值视为 0 再进行减一操作。如果 key 的值不是整型字符串或超出 64 位有符号整型范围,则会报错。返回值为减一后的整数值。

DECR key
EXISTS mykey
(integer) 0

DECR mykey
(integer) -1

SET mykey "10"
"OK"

DECR mykey
(integer) 9

SET mykey "234293482390480948029348230948"
"OK"

DECR mykey
(error) value is not an integer or out of range

SET mykey 'not a number'
"OK"

DECR mykey
(error) value is not an integer or out of range

1.1.10 DECYBY

DECRBY 命令用于将 key 对应的字符串形式的数字减去指定的值。如果 key 不存在,则默认将其值视为 0 再进行减法操作。如果 key 的值不是整型字符串或超出 64 位有符号整型范围,则会报错。返回值为减法运算后的整数值。

DECRBY key decrement
redis> EXISTS mykey
(integer) 0

redis> DECRBY mykey 3
(integer) -3

redis> SET mykey "10"
"OK"

redis> DECRBY mykey 3
(integer) 7

redis> DECRBY mykey "not a number"
(error) ERR value is not an integer or out of range

redis> SET mykey "234293482390480948029348230948"
"OK"

redis> DECRBY mykey 3
(error) value is not an integer or out of range

redis> SET mykey 'not a number'
"OK"

redis> DECRBY mykey 3
(error) value is not an integer or out of range

1.1.11 INCRBYFLOAT

INCRBYFLOAT 命令用于将 key 对应的字符串形式的浮点数加上指定的值。如果指定的值为负数,则视为减去该值。如果 key 不存在,则默认其值为 0。如果 key 的值不是字符串形式的浮点数,或格式不正确,则会报错。命令支持使用科学计数法表示浮点数。返回值为加/减运算后的浮点数值。

INCRBYFLOAT key increment
redis> SET mykey 10.50
"OK"

redis> INCRBYFLOAT mykey 0.1
"10.6"

redis> INCRBYFLOAT mykey -5
"5.6"

redis> SET mykey 5.0e3
"OK"

redis> INCRBYFLOAT mykey 2.0e2
"5200"

许多存储系统和编程语言通过 CAS 机制实现计数功能,这通常会带来一定的 CPU 开销。而在 Redis 中,由于采用单线程架构,所有命令在服务端都按顺序执行,因此无需引入 CAS 机制,从而避免了额外的性能开销。

1.1.12 APPEND

如果 key 存在且对应的是一个字符串,APPEND 命令会将指定的 value 追加到原有字符串的末尾;如果 key 不存在,则该命令的效果等同于 SET 命令。返回值为追加操作完成后字符串的长度。

APPEND KEY VALUE
redis> EXISTS mykey
(integer) 0

redis> APPEND mykey "Hello"
(integer) 5

redis> GET mykey
"Hello"

redis> APPEND mykey " World"
(integer) 11

redis> GET mykey
"Hello World"

1.1.13 GETRANGE

GETRANGE 命令用于返回 key 对应字符串的子串,子串范围由 start 和 end 参数确定(左闭右闭)。支持使用负数表示倒数位置,例如,-1 表示倒数第一个字符,-2 表示倒数第二个字符,依此类推。超出范围的偏移量会根据字符串的长度自动调整为有效范围。返回值为截取后的子串。

GETRANGE key start end
SET mykey "This is a string"
"OK"

GETRANGE mykey 0 3
"This"

GETRANGE mykey -3 -1
"ing"

GETRANGE mykey 0 -1
"This is a string"

GETRANGE mykey 10 100
"string"

1.1.13 SETRANGE

SETRANGE 命令用于从指定偏移量开始覆盖字符串的一部分内容。返回值为替换后字符串的长度。

SETRANGE key offset value
redis> SET key1 "Hello World"
"OK"

redis> SETRANGE key1 6 "Redis"
(integer) 11

redis> GET key1
"Hello Redis"

1.1.14 STRLEN

STRLEN 命令用于获取 key 对应字符串的长度。如果 key 的值不是字符串类型,则返回错误;如果 key 不存在,则返回 0。返回值为字符串的长度。

STRLEN key
SET mykey "Hello world"
"OK"

STRLEN mykey
(integer) 11

STRLEN nonexisting
(integer) 0

1.1.15 命令小结

命令执行效果时间复杂度
set key value [key value…]设置 key 的值为 valueO(k),k 是键的个数
get key获取 key 的值O(1)
del key [key …]删除指定的 keyO(k),k 是键的个数
mset key value [key value…]批量设置多个 key 和 valueO(k),k 是键的个数
mget key [key …]批量获取多个 key 的值O(k),k 是键的个数
incr key将指定 key 的值加 1O(1)
decr key将指定 key 的值减 1O(1)
incrby key n将指定 key 的值加 nO(1)
decrby key n将指定 key 的值减 nO(1)
incrbyfloat key n将指定 key 的值加 n(浮点数)O(1)
append key value将 value 追加到指定 key 的值后面O(1)
strlen key获取指定 key 的值的长度O(1)
setrange key offset value从指定偏移位置开始覆盖 key 的值O(n),n 是字符串长度,通常视为 O(1)
getrange key start end获取指定 key 的从 start 到 end 的部分值O(n),n 是字符串长度,通常视为 O(1)

1.2 内部编码

字符串类型的内部编码有 3 种:

内部编码类型描述适用场景
int8 字节的长整型。当值是可以转换为 64 位整数的字符串时。
embstr小于等于 39 字节的字符串。当值是长度小于等于 39 字节的字符串时。
raw大于 39 字节的字符串。当值是长度大于 39 字节的字符串时。
127.0.0.1:6379> set key 6379
OK

127.0.0.1:6379> object encoding key
"int"
127.0.0.1:6379> set key "hello"
OK

127.0.0.1:6379> object encoding key
"embstr"
127.0.0.1:6379> set key "one string greater than 39 bytes ........"
OK

127.0.0.1:6379> object encoding key
"raw"

1.3 字符串典型使用场景

1.3.1 缓存功能

在典型的缓存使用场景中,Redis 通常作为缓存层,MySQL 作为存储层,大部分请求数据直接从 Redis 获取。由于 Redis 支持高并发访问,缓存层能够显著加速读写操作,同时有效降低后端数据库的压力。

在这里插入图片描述

在根据用户 uid 获取用户信息的场景中,系统首先从 Redis 中获取用户信息(假设用户信息存储在键 “user:info:” 中)。如果 Redis 未命中(缓存 miss),则从 MySQL 中查询对应信息,并将查询结果写入 Redis 缓存后返回。

// 根据 uid 得到 Redis 的键
String key = "user:info:" + uid;

// 尝试从 Redis 中获取对应的值
String value = Redis 执行命令:get key;

// 如果缓存命中(hit)
if (value != null) {
    // 假设用户信息按照 JSON 格式存储
    UserInfo userInfo = JSON 反序列化(value);
    return userInfo;
}

// 如果缓存未命中(miss)
if (value == null) {
    // 从数据库中根据 uid 获取用户信息
    UserInfo userInfo = MySQL 执行 SQL:select * from user_info where uid = <uid>;

    // 如果表中没有 uid 对应的用户信息
    if (userInfo == null) {
        响应 404;
        return null;
    }

    // 将用户信息序列化成 JSON 格式
    String jsonValue = JSON 序列化(userInfo);

    // 写入缓存,并设置过期时间为 1 小时(3600 秒)
    Redis 执行命令:set key jsonValue ex 3600;

    // 返回用户信息
    return userInfo;
}

与 MySQL 等关系型数据库不同,Redis 没有表和字段这样的命名空间,对键名也没有强制要求(除了一些特殊字符不能使用)。但是合理的键名设计可以有效防止键冲突并提升项目的可维护性。推荐的方式是使用类似 “业务名:对象名:唯一标识:属性” 的格式。例如,如果 MySQL 数据库名为 vs,用户表名为 user_info,对应的 Redis 键名可以设计为 “vs:user_info:6379” 或 “vs:user_info:6379:name”。如果 Redis 只被单一业务使用,可以省略业务名,如直接使用 “user_info:6379”。

同时,为了避免键名过长影响 Redis 性能,可以使用团队内部认可的缩写替代。例如,将 “user:6379:friends:messages:5217” 简化为 “u:6379🇫🇷m:5217”。合理缩短键名不仅能提高性能,还能减少存储空间的浪费,从而优化 Redis 的整体效率。

1.3.2 计数功能

许多应用会使用 Redis 作为计数的基础工具,因为他能够实现快速计数和查询缓存功能,同时支持数据异步处理或持久化到其他数据源。例如在视频网站中,视频播放次数的统计可以通过 Redis 实现:每当用户播放一次视频,对应的视频播放数便会自动加 1。

在这里插入图片描述

// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {
    String key = "video:" + vid;
    long count = Redis 执行命令:incr key;
    return count;
}

1.3.3 共享会话

在分布式 Web 服务中,用户的 Session 信息通常保存在各自的服务器上,但这种方式会带来一个问题:由于负载均衡的存在,用户的访问请求会被分配到不同的服务器上,且无法保证每次请求都分配到同一台服务器。这可能导致用户在刷新页面后需要重新登录,而这种体验是用户无法接受的。

在这里插入图片描述

为了解决这个问题,可以使用 Redis 对用户的 Session 信息进行集中管理。如图 2-13 所示,在这种模式下,只需保证 Redis 的高可用性和可扩展性,无论用户被负载均衡到哪台 Web 服务器上,都可以集中从 Redis 中查询和更新 Session 信息,从而避免重复登录的问题。

在这里插入图片描述

1.3.4 手机验证码

在这里插入图片描述

// 发送验证码
String sendValidationCode(String phoneNumber) {
    String key = "shortMsg:limit:" + phoneNumber;

    // 设置过期时间为 1 分钟(60 秒),使用 NX 仅在不存在时设置成功
    boolean r = Redis 执行命令:set key 1 ex 60 nx;

    if (!r) {
        // 说明之前已经设置过该手机的验证码
        long c = Redis 执行命令:incr key;

        if (c > 5) {
            // 超过一分钟内 5 次的限制,禁止发送
            return null;
        }
    }

    // 如果之前没有设置验证码,或者次数没有超过 5 次
    String validationCode = 生成随机的 6 位数验证码();
    String validationKey = "validation:" + phoneNumber;

    // 验证码 5 分钟(300 秒)内有效
    Redis 执行命令:set validationKey validationCode ex 300;

    // 返回验证码,用于通过短信发送给用户
    return validationCode;
}

// 验证用户输入的验证码是否正确
boolean validateCode(String phoneNumber, String validationCode) {
    String validationKey = "validation:" + phoneNumber;

    // 获取 Redis 中存储的验证码
    String value = Redis 执行命令:get validationKey;

    if (value == null) {
        // 没有该手机的验证码记录,验证失败
        return false;
    }

    // 验证输入的验证码是否正确
    return value.equals(validationCode);
}

二: Hash 哈希

几乎所有主流编程语言都支持哈希类型,名称可能不同,例如哈希、字典、关联数组或映射等。在 Redis 中,哈希类型的值本身也是一个键值对结构,形式为 key = “key”,value = { {field1, value1}, …, {fieldN, valueN} }。其中,哈希类型的映射关系通常被称为 field-value,用于区分 Redis 整体的键值对(key-value)。需要注意,此处的 value 是指 field 对应的值,而非 key 对应的值,不同上下文中 value 的含义可能会有所不同。

在这里插入图片描述

2.1 常用命令

2.1.1 HSET

HSET 命令用于设置哈希表中指定字段(field)的值(value)。返回值为新增字段的数量。

HSET key field value [field value ...]
redis> HSET myhash field1 "Hello"
(integer) 1

redis> HGET myhash field1
"Hello"

2.1.2 HGET

获取哈希表中指定字段的值。返回值为字段对应的值,若字段不存在则返回 nil。

HGET key field
redis> HSET myhash field1 "foo"
(integer) 1

redis> HGET myhash field1
"foo"

redis> HGET myhash field2
(nil)

2.1.3 HEXISTS

HEXISTS 判断哈希表中是否存在指定字段。返回 1 表示存在,0 表示不存在。

HEXISTS key field
redis> HSET myhash field1 "foo"
(integer) 1

redis> HEXISTS myhash field1
(integer) 1

redis> HEXISTS myhash field2
(integer) 0

2.1.4 HDEL

HDEL 命令用于删除哈希表中指定的字段。返回值为成功删除的字段数量。

HDEL key field [field ...]
redis> HSET myhash field1 "foo"
(integer) 1

redis> HDEL myhash field1
(integer) 1


redis> HDEL myhash field2
(integer) 0

2.1.5 HKEYS

HKEYS 命令用于获取哈希表中所有字段的名称。返回值为字段名称列表。

HKEYS key
redis> HSET myhash field1 "Hello"
(integer) 1

redis> HSET myhash field2 "World"
(integer) 1

redis> HKEYS myhash
1) "field1"
2) "field2"

2.1.6 HVALS

HVALS 命令用于获取哈希表中所有字段的值。返回值为值的列表。

HVALS key
redis> HSET myhash field1 "Hello"
(integer) 1

redis> HSET myhash field2 "World"
(integer) 1

redis> HVALS myhash
1) "Hello"
2) "World"

2.1.7 HGETALL

HGETALL 命令用于获取哈希表中所有字段及其对应的值。返回值为字段和值的集合。

HGETALL key
redis> HSET myhash field1 "Hello"
(integer) 1

redis> HSET myhash field2 "World"
(integer) 1

redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"

2.1.8 HMGET

HMGET 命令用于一次获取哈希表中多个字段的值。返回值为字段对应的值列表,若字段不存在则返回 nil。

HMGET key field [field ...]
HSET myhash field1 "Hello"
(integer) 1

HSET myhash field2 "World"
(integer) 1

HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)

2.1.9 HLEN

HLEN 命令用于获取哈希表中字段的总数。返回值为字段的数量。

HLEN key
redis> HSET myhash field1 "Hello"
(integer) 1

redis> HSET myhash field2 "World"
(integer) 1

redis> HLEN myhash
(integer) 2

2.1.10 HSETNX

HSETNX 命令用于在字段不存在时,为哈希表设置指定字段和值。返回值:1 表示设置成功,0 表示设置失败(字段已存在)。

HSETNX key field value
redis> HSETNX myhash field "Hello"
(integer) 1

redis> HSETNX myhash field "World"
(integer) 0

redis> HGET myhash field
"Hello"

2.1.11 HINCRBY

HINCRBY 命令用于为哈希表中指定字段的数值增加指定值。返回值为字段更新后的值。

HINCRBY key field increment
redis> HSET myhash field 5
(integer) 1

redis> HINCRBY myhash field 1
(integer) 6

redis> HINCRBY myhash field -1
(integer) 5

redis> HINCRBY myhash field -10
(integer) -5

2.1.12 HINCRBYFLOAT

HINCRBYFLOAT 命令是 HINCRBY 的浮点数版本,用于为哈希表中指定字段的数值增加指定的浮点数值。返回值为字段更新后的值。

HINCRBYFLOAT key field increment
redis> HSET mykey field 10.50
(integer) 1

redis> HINCRBYFLOAT mykey field 0.1
"10.6"

redis> HINCRBYFLOAT mykey field -5
"5.6"

redis> HSET mykey field 5.0e3
(integer) 0

redis> HINCRBYFLOAT mykey field 2.0e2
"5200"

2.1.13 命令小结

命令执行效果时间复杂度
hset key field value设置指定字段的值O(1)
hget key field获取指定字段的值O(1)
hdel key field [field…]删除指定字段O(k),k 是字段个数
hlen key计算字段总数O(1)
hgetall key获取所有字段及其对应的值O(k),k 是字段个数
hmget key field [field…]批量获取多个字段的值O(k),k 是字段个数
hmset key field value [field value…]批量设置多个字段的值O(k),k 是字段个数
hexists key field判断指定字段是否存在O(1)
hkeys key获取所有字段O(k),k 是字段个数
hvals key获取所有值O(k),k 是字段个数
hsetnx key field value设置值,但仅在字段不存在时设置成功O(1)
hincrby key field n将字段的值增加指定的整数O(1)
hincrbyfloat key field n将字段的值增加指定的浮点数O(1)
hstrlen key field计算字段对应值的字符串长度O(1)

2.2 内部编码

哈希的内部编码有两种:

内部编码类型使用条件优势
ziplist当哈希类型元素个数小于 hash-max-ziplist-entries(默认 512 个),且所有值小于 hash-max-ziplist-value(默认 64 字节)时使用。采用紧凑结构,节省内存。
hashtable当哈希类型不满足 ziplist 条件(如元素过多或值过大)时使用。读写效率高,时间复杂度为 O(1)。
  1. 当 field 个数比较少且没有大的 value 时,内部编码为 ziplist:
127.0.0.1:6379> hmset hashkey f1 v1 f2 v2
OK

127.0.0.1:6379> object encoding hashkey
"ziplist"
  1. 当有 value 大于 64 字节时,内部编码会转换为 hashtable:
127.0.0.1:6379> hset hashkey f3 "one string is bigger than 64 bytes ...  省略 ..."
OK

127.0.0.1:6379> object encoding hashkey
"hashtable"
  1. 当 field 个数超过 512 时,内部编码也会转换为 hashtable:
127.0.0.1:6379> hmset hashkey f1 v1 h2 v2 f3 v3 ... 省略 ... f513 v513
OK
127.0.0.1:6379> object encoding hashkey
"hashtable"

2.3 Hash 典型使用场景

2.3.1 缓存信息

在这里插入图片描述

在这里插入图片描述

相比使用 JSON 格式的字符串来缓存用户信息,哈希类型更加直观,并且在更新操作上更加灵活。通过将每个用户的 ID 作为键的后缀,并使用多个 field-value 对来表示用户的各个属性,可以实现如下的设计:

UserInfo getUserInfo(long uid) {
    // 根据 uid 得到 Redis 的键
    String key = "user:" + uid;

    // 尝试从 Redis 中获取对应的值
    Map<String, String> userInfoMap = Redis 执行命令:hgetall key;

    // 如果缓存命中(hit)
    if (userInfoMap != null && !userInfoMap.isEmpty()) {
        // 将映射关系还原为对象形式
        UserInfo userInfo = 利用映射关系构建对象(userInfoMap);
        return userInfo;
    }

    // 如果缓存未命中(miss)
    // 从数据库中,根据 uid 获取用户信息
    UserInfo userInfo = MySQL 执行 SQL:select * from user_info where uid = <uid>;

    // 如果表中没有 uid 对应的用户信息
    if (userInfo == null) {
        // 响应 404
        return null;
    }

    // 将缓存以哈希类型保存
    Redis 执行命令:hmset key name userInfo.name age userInfo.age city userInfo.city;

    // 设置缓存过期时间为 1 小时(3600 秒)
    Redis 执行命令:expire key 3600;

    // 返回用户信息
    return userInfo;
}
区别描述
稀疏性与结构化哈希类型是稀疏的,每个键可以有不同的 field;关系型数据库是完全结构化的,新增列时所有行必须设置值(即使为 null)。
复杂查询能力关系型数据库支持复杂的关系查询,如联表查询和聚合查询;而 Redis 模拟这些查询几乎不可能,且维护成本高。

在这里插入图片描述

截至目前,我们已经掌握了三种方法来缓存用户信息。以下将展示这三种方案的实现方式,并对其优缺点进行分析。

缓存方式优点缺点
原生字符串类型实现简单,针对个别属性变更非常灵活。占用过多的键,内存消耗大,用户信息在 Redis 中分散,缺乏内聚性,实际使用场景较少。
序列化字符串类型(如 JSON)适合整体操作的信息,编程简单;选择合适的序列化方案可以提高内存使用效率。序列化和反序列化需要一定的开销,对个别属性的操作非常不灵活。
哈希类型简单、直观、灵活,特别适合信息的局部变更或获取操作。需要管理 ziplist 和 hashtable 两种内部编码的转换,可能导致内存消耗较大。
  1. 原生字符串类型
set user:1:name James
set user:1:age 23
set user:1:city Beijing
  1. 序列化字符串类型
set user:1 经过序列化后的⽤⼾对象字符串
  1. 哈希类型
hmset user:1 name James age 23 city Beijing
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ice___Cpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值