Redis(一)简介、基本数据类型、通用指令

一、Redis 的简介、特点、应用

    Redis 是互联网技术领域使用最为广泛的 存储中间件 ,它是「Remote Dictionary Service」的首字母缩写,也就是「远程字典服务」。
    跟随 Redis 官网,https://redis.io/,来学习 Redis 吧 😝。
在这里插入图片描述
    译:Redis是一种开放源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存 和 消息代理 message broker。 它支持数据结构,例如字符串 string,哈希 hash ,列表 lsit ,集合 set ,带范围查询的排序集 sorted_set,位图,超级日志,带有半径查询和流的地理空间索引。Redis 具有内置的复制,Lua 脚本,LRU 驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供高可用性
    
    Redis 在数据库中,称为 键值存储 。其中所有的数据都是采用 key : value 的形式存储,通过这个唯一 key 值来获取相应的 value 数据。不同类型的数据结构的差异就在于 value 的结构不一样。 key 部分永远都是字符串
    键值存储的本质是能够在键内部存储一些数据(称为值)的能力。仅当我们知道用于存储数据的确切 key 时,以后才能检索该数据。
    Redis 通常被称为数据结构服务器,因为它具有外部键值外壳,但是每个值可以包含复杂的数据结构,例如字符串,列表,哈希或有序数据结构数据结构,例如超级日志。
    


  • Redis 特点:
        Redis 是常见的 Nosql 【非关系型的数据库】 数据库,它可以弥补 关系型数据库的缺陷,比如,在海量用户、高并发的应用场景下,关系型数据库容易遇到性能瓶颈——磁盘 IO 性能低下;扩展瓶颈——数据关系复杂、扩展性差、不易于大规模集群。而 作为 非关系型数据库,Redis 具有以下特点:
  • 内部采用单线程机制 进行工作
  • 去除了复杂的数据间关系
  • 可扩容、可伸缩
  • 大数据量下 高性能【官方提供测试数据,50 个并发执行 100000 个请求,读 的速度是 110000 次/s,写 速度是 81000次/s】
  • 高可用
  • 提供持久化支持,可以进行数据灾难恢复

  • Redis 应用
  • 为 热点数据 加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等
  • 任务队列,如秒杀、抢购、购票排队等
  • 即时信息查询,如 各位排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设备信号等
  • 时效性信息控制,如 验证码控制、投票控制等
  • 分布式数据共享,如分布式集群架构中的 session 分离
  • 消息队列
  • 分布式锁

👉 启动 Redis

    在 cmd 命令行中,先切换到 Redis 安装的盘下,然后使用 redis-server.exe redis.windows.conf 启动服务端:
在这里插入图片描述
接下来,启动客户端:
在这里插入图片描述
(Redis 的默认端口是 6379,这个端口号也不是随机选的,而是由手机键盘字母「MERZ」的位置决定的。 Redis 创始人将「MERZ」作为「愚蠢」的代名词。🤭)
    如果想清除屏幕信息,使用 clear 命令。
    如果想获取命令帮助文档,使用 help
在这里插入图片描述
    如果想退出客户端命令行模式,使用 quitexit 、 或者 Esc 按键。
    

二、Redis 基本数据类型与操作

1、string 类型

    Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用 预分配冗余空间 的方式来减少内存的频繁分配,如图所示,内部为当前字符串实际分配的空间, capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是:字符串最大长度为 512M。
在这里插入图片描述

  • SET 设置 键 和 关联值

    作为第一个示例,我们可以使用命令SET将值 “fido” 存储在键 “server:name”中:

SET server:name "fido"

在这里插入图片描述

    

  • GET 获取 键 对应的关联值

    Redis将永久存储我们的数据,因此我们稍后可以询问“密钥服务器:名称中存储的值是多少?” Redis 会回复 “ fido” :

GET server:name => "fido"

在这里插入图片描述
🙌可以用于 高热度数据访问加速。例如 微博大V 主页显示粉丝数与微博数量。在 redis 中为 大V 用户设定用户信息,以 用户主键 和 属性值 作为 key,后台设定定时刷新策略即可。以 json 格式存储 大V用户信息,定时刷新。
eg: user🆔3506728370:fans → 12210947
eg: user🆔3506728370:blogs → 6164
eg: user🆔3506728370:focuss → 83

    

  • EXISTS 测试给定 key 是否存在
EXISTS server:name => 1
EXISTS server:blabla => 0

在这里插入图片描述
    如果字符串 string 以整数的形式展示,可以作为数字操作使用。
    Redis 提供的其他基本操作包括:

  • DEL 删除给定的 键 和 关联值
  • INCR 原子地增加 存储在给定键上的数字
SET connections 10
INCR connections => 11
INCR connections => 12
DEL connections
INCR connections => 1

关于 INCR 的逻辑很简单,分为 3 步:
☝ x = GET count
✌ x = x + 1
👌 SET count x

    问题在于,只有在有单个客户端使用 key 的情况下,以这种方式进行增量操作才有效。来看看 两个客户端同时访问此 key 会发生什么:
(1)客户端 A 读取计数为 10。
(2)客户端 B 读取的计数为 10。
(3)客户 A 增加 10,并将计数设置为 11。
(4)客户端 B 增加 10,并将计数设置为 11。
    我们希望该值为12,但实际上为11。这是因为以这种方式增加值不是原子操作。在Redis中调用 INCR命令 可以防止这种情况的发生,因为它是原子操作。
     由单个命令实现的所有 Redis 操作都是原子的,包括对更复杂的数据结构进行操作的操作。因此,当您使用可修改某些值的Redis命令时,无需考虑并发访问。

🎼 插曲:突然出现报错:
在这里插入图片描述
可以看到,强制把 redis 快照关闭了 导致不能持久化,解决方法:输入 config set stop-writes-on-bgsave-error no 命令。

在这里插入图片描述

  • INCRBY 将 key 中包含的数字增加特定数量:
INCRBY connections 100 => 101

在这里插入图片描述
🙌可以用于为数据库表主键提供生成策略 。

    如果要增加 小数 数值,可以使用 INCRBYFLOAT 。
    

  • DECR、DECRBY 减少 key 的值。
DECR connections => 100
DECRBY connections 10 => 90

在这里插入图片描述

    string 类型 在 Redis 内部存储默认就是一个字符串,当遇到增减类操作 INCR,DECR 时会转成数值型进行计算。而数值进行操作的数据,如果 原始数据不能转成数值,或超越了 Redis 数值上限范围,将报错。
【9223372036854775807(java中long型数据最大值,Long.MAX_VALUE)】
    

  • MSET 添加/修改多个数据
MSET key1 "value1" key2 "value2"
  • MGET 获取多个数据
MGET key1 => 1)"value1", 2)"value2"

在这里插入图片描述
    
    


🖖 关于 单数据操作 与 多数据操作 的 选择
在这里插入图片描述

    可以看到,set 发送指令【上图小钟表】、执行指令【上图大钟表】、返回结果 【上图小钟表】都是花费时间的。 如果一次执行完 消耗的时长非常大的话,对于单线程操作,还是使用 多指令更合适。


    

  • STRLEN 获取数据字符个数(字符串长度)
STRLEN key1 => 6

在这里插入图片描述

  • APPEND 追加信息到原始字符串(如果原始信息存在就追加,否则新建)
APPEND key1 "+value11"

在这里插入图片描述

  • EXPIRE 设置数据具有指定的生命周期

    通过 EXPIRE 命令 可以告诉 Redis key 只能存在一定时间,这是以 秒 为单位的。并且有类似的 PEXPIRE 和 PTTL 进行操作的,是以毫秒为单位的。

SET resource:lock "Redis Demo"
EXPIRE resource:lock 120

在这里插入图片描述
     这将导致密钥 resource:lock 在120秒内 被删除。
     SETEX key seconds value 也可以起到相同的作用,单位是 秒;PSETEX key milliseconds value,单位是毫秒。
    


    Redis 所有的数据结构都可以设置过期时间,时间到了,Redis 会自动删除相应的对象。
    需要注意的是过期是以对象为单位,比如一个 hash 结构的过期是整个 hash 对象的过期,而不是其中的某个子 key。


🙌可以用于与 “热点”、“时效性” 相关的业务场景,比如:
     热门商品不能一直处于热门期,每种商品热门期维持 3天,3 天后自动取消热门。
     新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性;
    
    

  • TTL 测试 key 存在时间
         可以使用 TTL 命令测试 key 存在多长时间。它返回直到将其删除的秒数。
TTL resource:lock => 113
// after 113s
TTL resource:lock => -2

在这里插入图片描述

     key 的 TTL 为 -2 表示该键不存在(不再存在)。而一个 key 的 TTL 为 -1 意味着 它永远都不会过期。

     请注意,如果通过 SET 设置一个键,其 TTL 将被重置

SET resource:lock "Redis Demo 1"
EXPIRE resource:lock 120
TTL resource:lock => 119
SET resource:lock "Redis Demo 2"
TTL resource:lock => -1

在这里插入图片描述

     SET 命令可以接受进一步的参数,直接设置生存时间(TTL)到 key,这样可以在单个原子操作中改变一个 key 的值 并 同时设置其 TTL :

SET resource:lock "Redis Demo 3" EX 5
TTL resource:lock => 5

在这里插入图片描述

  • PERSIST 过期时间设置并再次将其永久化。
 PERSIST resource:lock
 TTL resource:lock => -1

在这里插入图片描述

     可以看到,第一次持久化 resource:lock 失败了,应该是因为 设置的过期时间是 5 s,太短啦,改成 100 之后就持久化成功了。
    
    
🐾 string 类型数据操作的注意事项
① 返回值表示运行结果是否成功
(integer) 0 → false 失败
(integer) 1 → true 成功

② 返回值表示运行结果值
(integer) 3 → 3 :3个
(integer) 1 → 1 :1个

③数据未获取到:(nil)等同于null

  • 数据最大存储量
    512MB
  • 数值计算最大范围(java中的long的最大值)
    9223372036854775807
2、list 类型

     Redis 还支持几种更复杂的数据结构。我们要看的第一个是列表 list 。
    Redis 的列表 list 相当于 Java 语言里面的 LinkedList,是一系列有序值,即 存储多个数据,并对数据进入存储空间的顺序进行区分 。其 底层使用 双向链表 存储结构实现。它是链表而不是数组。这意味着
list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n)。 当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。
     如果再深入一点,会发现 Redis 底层存储的还不是一个简单的 linkedlist,而是称之为快速链表 quicklist 的一个结构。首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是 压缩列表 。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间,而且会加重内存的碎片化。比如这个列表里存的只是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next 。所以 Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
     一些与列表 list 交互的重要的命令是 RPUSH,LPUSH,LLEN,LRANGE,LPOP 和 RPOP。只要不是已经作为另外一种类型存在,就可以立即将其用作列表。
     这个概念通常适用于每个 Redis 数据结构:不必先创建 key,然后再添加,但是可以直接使用命令来添加新元素。作为副作用,如果 key 不存在,则会创建该 key。类似地,执行某些命令后 将变为空的 key 将自动从键空间中删除。

  • RPUSH 将 新元素放在列表的末尾。
RPUSH friends "Alice"
RPUSH friends "Bob"
  • LPUSH 将新元素放在列表的开头。
LPUSH friends "Sam"

在这里插入图片描述
    右边进 RPUSH 左边出 LPOP ➡ 队列。
    右边进 RPUSH 右边出 RPOP ➡ 栈。
    

  • LRANGE 给出了列表的子集。
         它以要检索的第一个元素的索引为第一个参数,以要检索的最后一个元素的索引为第二个参数。第二个参数的值 -1 表示检索元素直到列表的末尾,-2 表示包括最多倒数第二个,依此类推。
LRANGE friends 0 -1 => 1) "Sam", 2) "Alice", 3) "Bob"
LRANGE friends 0 1 => 1) "Sam", 2) "Alice"
LRANGE friends 1 2 => 1) "Alice", 2) "Bob"

在这里插入图片描述

     到目前为止,我们探索了可以向列表中添加元素的命令以及 可以检查列表范围的 LRANGE 。Redis 列表的基本功能是 能够删除列表开头或结尾的元素,并同时将其返回给客户端。

  • LPOP 从列表中删除第一个元素并返回它。
LPOP friends => "Sam"
  • RPOP 从列表中删除最后一个元素并返回它。
RPOP friends => "Bob"

把 “Sam” 和 “Bob” 都删除掉了,列表现在仅包含一个元素 “Alice” 了:

LLEN friends => 1
LRANGE friends 0 -1 => 1) "Alice"
  • LLEN 获取列表的当前长度。
    在这里插入图片描述

  • RPUSH 和 LPUSH 命令都是可变参数,以便可以指定在一条命令执行中指定多个元素。在操作后返回列表的总长度。

RPUSH friends 1 2 3 => 4
LLEN friends => 4

在这里插入图片描述

  • BLPOP、BRPOP 移除 并 获取列表的头 / 尾 元素, 如果列表没有元素会阻塞,直到等待超时或发现可弹出元素为止。
 BLPOP friends 1000 => 1)"friends", 2)"Alice"
 brpop key1 [key2] timeout => 1)"friends", 2)"3"

在这里插入图片描述

  • BRPOPLPUSH 从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
    在这里插入图片描述
    🙌可以用于 具有操作先后顺序的数据控制 。
    🙌可以用于 做异步队列使用。将需要延后处理的任务结构体序列化成字符
    串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。
        
    🐾 list 类型数据操作注意事项
  • list 中保存的数据都是 string 类型的,数据总容量是有限的,最多 2^32 - 1 个元素 (4294967295)。
  • list 具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作。
  • 获取全部数据操作结束索引设置为 -1 。
  • list 可以对数据进行分页操作,通常第一页的信息来自于list,第 2 页及更多的信息通过数据库的形式加载 。
3、set 类型

     下一个数据结构是一个集合 set。集合 与 列表 list 相似,不同之处在于它没有特定的顺序,每个元素只能出现一次。这两种数据结构都非常有用,因为在列表中 访问靠近 顶部 或 底部 的元素是快速的,并且保留元素的顺序,但是在 set 中可以快速测试成员关系,即 立即知道 是否添加了给定的元素。此外,在一个 set 中,给定元素只能存在于单个副本中(不允许重复的意思)。
    Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL。当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。
🙌 利用 set 集合的数据 去重 特征,记录各种访问数据。
    使用 set 时,一些重要的命令是SADD,SREM,SISMEMBER,SMEMBERS 和 SUNION。

  • SADD 将给定成员添加到集合中,该命令也是可变参数。如果我们尝试添加的元素已经存在,则返回 0,否则 返回 1:
SADD superpowers "flight"
SADD superpowers "x-ray vision" "reflexes"
  • SREM从集合中删除给定的成员,返回 1【存在】 或 0 【否】表示该成员是否确实存在。
SREM superpowers "reflexes" => 1
SREM superpowers "making pizza" => 0

在这里插入图片描述

  • SISMEMBER 测试给定值是否在集合中。如果该值存在,则返回1,否则返回0 。
SISMEMBER superpowers "flight" => 1
SISMEMBER superpowers "reflexes" => 0

在这里插入图片描述

  • SMEMBERS 返回此集合的所有成员的列表。
SMEMBERS superpowers => 1) "flight", 2) "x-ray vision"

在这里插入图片描述

  • SCARD 获取集合数据总量
SCARD superpowers => 3

在这里插入图片描述

  • SUNION 组合两个或更多集合,并返回所有元素的列表。
SADD birdpowers "pecking"
SADD birdpowers "flight"
SUNION superpowers birdpowers => 1) "pecking", 2) "x-ray vision", 3) "flight"

在这里插入图片描述

  • SPOP
         set 还有与 LPOP 和 RPOP 非常相似的命令 ,比如 SPOP,以便从集合中提取元素 并 将它们通过一次操作返回给客户端。但是,由于 set 不是有序的数据结构,因此在这种情况下返回(删除)的元素完全是随机的。 key 名称后面的 SPOP 参数是我们希望它返回并从集合中删除的元素数。
SADD letters a b c d e f => 6
SPOP letters 2 => 1) "c" 2) "a"

现在,该集合将仅包含其余元素:

SMEMBERS letters => 1) "b" 2) "d" 3) "e" 4) "f"

在这里插入图片描述
     可以看到,我使用 “SPOP” 命令后,删除掉的是 “c” 和 “f”,和例子还不一样。

🙌可以用于 随机 推荐类信息检索。(例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐, 大V推荐等 )

    

  • SRANDMEMBER 返回随机元素 而不将其从集合中删除。其参数类似于 SPOP,但是如果指定负数 而不是正数,它也可能返回重复元素。
    在这里插入图片描述

  • SINTER、SUNION、SDIFF 交、并、差 集
    在这里插入图片描述

  • SINTERSTORE、SUNIONSTORE、SDIFFSTORE 求两个集合的交、并、差集并存储到指定集合中
    在这里插入图片描述


     set 是一种非常方便的数据类型,但是由于它没有排序,因此对于许多问题来说效果不佳。这就是 Redis 1.2 引入 排序集 的原因。


4、sort_set 类型

     排序集 sort_set 类似于常规 set ,但是现在每个值都有一个关联的分数 score 。该分数用于对集合中的元素进行排序。
     sort_set 类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。它的内部实现用的是一种叫着「跳跃列表」(因为 zset 要支持随机的插入和删除,所以它不好使用数组来表示。)的数据结构。zset 中最后一个 value 被移除后,数据结构自动删除,内存被回收。

🙌 可以用于需要 排序 的数据。

  • ZADD 添加数据
ZADD hackers 1940 "Alan Kay"
ZADD hackers 1906 "Grace Hopper"
ZADD hackers 1953 "Richard Stallman"
ZADD hackers 1965 "Yukihiro Matsumoto"
ZADD hackers 1916 "Claude Shannon"
ZADD hackers 1969 "Linus Torvalds"
ZADD hackers 1957 "Sophie Wilson"
ZADD hackers 1912 "Alan Turing"

在这个示例中,得分是出生年份,而值是著名黑客的名字。

  • ZRANGE 获取数据
ZRANGE hackers 2 4 => 1) "Claude Shannon", 2) "Alan Kay", 3) "Richard Stallman"

在这里插入图片描述

  • ZREM 删除数据
ZREM hackers "Grace Hopper" => 1

在这里插入图片描述

  • ZRANGEBYSCORES、ZREVRANGEBYSCORE 按范围获取数据
    在这里插入图片描述
  • ZREMRANGEBYRANK、ZREMRANGEBYSCORE 按范围删除数据
    在这里插入图片描述
  • ZCARD 获取集合数据总量
ZCARD hackers => 8

在这里插入图片描述

  • ZCOUNT 获取指定范围内数据数量
ZCOUNT hackers 1906 1957 => 6

在这里插入图片描述
    类似的,也有 交 ZINTERSTORE、并操作 ZUNIONSTORE 操作。
    
🐾 sorted_set 类型数据注意事项

  • score 保存的数据存储空间是 64 位,对应的整数范围为:
    -9007199254740992~9007199254740992 。
  • score 保存的数据也可以是一个双精度的 double 值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重 。
  • sorted_set 底层存储还是基于 set 结构的,因此数据不能重复,如果重复添加相同的数据,score 值将被反复覆盖,保留最后一次修改的结果 。
5、hash 类型

    简单的 strings,set 和 排序集合 sorted sets 已经完成了很多工作,但是 Redis 可以处理另一种数据类型:哈希 hash 。
    哈希是 字符串 字段 和 字符串 值 之间的映射,因此它们是 表示对象的理想数据类型。不同于 字符串 一次性需要全部序列化整个对象,hash 可以对用户结构中的每个字段单独存储。这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话就只能一次性全部读取,这样就会比较浪费网络流量。
    而 hash 类型,一个存储空间保存多个键值对数据 ,底层使用哈希表结构实现数据存储,如果 field 数量较少,存储结构优化为 类数组结构;如果field数量较多,存储结构使用 HashMap 结构。
在这里插入图片描述

    可以看到,hash 结构的三要素是 :key 、field 和 value 。

    Redis 的 hash 相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。不同的是,Redis 的 hash 的值只能是字符串,另外它们 rehash 的方式不一样,因为
Java 的 HashMap 在字典很大时,rehash 是个耗时的操作,需要一次性全 rehash。Redis 为了高性能,不能堵塞服务,所以采用了渐进式 rehash 策略。渐进式 rehash 会在 rehash 的同时,保留新旧两个 hash 结构,查询时会同时查询两个 hash 结构,然后在后续的定时任务中以及 hash 的子指令中,循序渐进地将旧 hash 的内容
一点点迁移到新的 hash 结构中。
在这里插入图片描述

  • HSET 设置哈希值
    (例如:用户具有多个字段(姓名,姓氏,年龄等))。
HSET user:1000 name "John Smith"
HSET user:1000 email "john.smith@example.com"
HSET user:1000 password "s3cret"
  • HGET 获取单个字段值:
HGET user:1001 name => "Mary Jones"

在这里插入图片描述

  • HGETALL 获取所有字段值
HGETALL user:1000

在这里插入图片描述

  • HDEL 删除字段值
HDEL user:1000 name

在这里插入图片描述

  • HMSET 一次设置多个字段
HMSET user:1001 name "Mary Jones" password "hidden" email "mjones@example.com"

在这里插入图片描述

  • HMGET 一次获取多个字段
HMGET user:1001 name password =>1)"Mary Jones",2)"hidden"

在这里插入图片描述
🙌可以用于 抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计 ,比如:
🙌 业务场景 1
电商网站购物车设计与实现
在这里插入图片描述
    仅分析购物车的 Redis 存储模型:添加、浏览、更改数量、删除、清空。不讨论 购物车 与 数据库间 持久化同步、购物车与订单间关系、未登录用户的购物车信息存储情况。
    以客户 id 作为 key,为每位客户创建一个 hash 存储结构存储对应的购物车信息。将商品编号作为 field,购买数量作为 value 进行存储,客户添加新的商品,就追加新的 field 和 value;客户浏览商品,就遍历 hash,更改商品数量,就 设置 value 值;客户删除商品,就删除对应的 field;客户清空购物车,就删除客户 id 对应的 key。

比如:先给用户 001 添加 100 份 g01 商品、200 份 g02 商品;给用户 002 添加 1 份 g02 商品、 7 份 g04 商品、100 份 g05 商品。并查看、修改,用户 001 又添加 5 份 g03 商品,然后删除 g01 商品,并把 g03 商品添加 100 份。
在这里插入图片描述
    ❌但是问题来了:当前设计是否加速了购物车的呈现? 并没有,当前仅仅是将数据存储到了 Redis 中,并没有起到加速的作用,我们现在只知道商品购买数量,但是 商品具体信息还需要二次查询数据库。
    👌解决方案:把每个购物车中的商品 保存成两条 field,field 1 用于保存购买数量;field 2 用于保存显示到购物车页面的信息,比如 文字描述、图片地址、所属商家信息等。


  • field1 专用于保存购买数量
            命名格式:商品id:nums
            保存数据:数值
  • field2 专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等
            命名格式:商品id:info
            保存数据:json
    在这里插入图片描述

🙌 业务场景 2
    销售手机充值卡的商家对 移动、联通、电信 的 30 元、50 元、100 元商品推出抢购活动,每种商品抢购上限 1000 张,可以以 商家id 为 key,参与抢购活动的商品id 为 field,商品数量为 value,抢购时使用降值的方式控制商品数量。

    

  • HSETNX 如果当前 key 对应的 field 有值,就不进行操作,如果没有值,才设置值
HSETNX key field value

在这里插入图片描述

  • HEXISTS 获取哈希表中是否存在指定的字段,存在则返回 1 ,否则返回 0。
HEXISTS user:1001 name => 1

    不过Redis 原则上只做数据的存储和保存,尽量不要把业务逻辑(如判断是否存在等)加进来😇 。

在这里插入图片描述

  • HKEYS 获取哈希表中所有的字段名
HKEYS user:1001 => 1)"name", 2)"password", 3)"email"

在这里插入图片描述

  • HVALS 获取哈希表中所有的字段值
HVALS user:1001 => 1)"Mary Jones", 2)"hidden", 3)"mjone@example.com"

在这里插入图片描述

    
    哈希字段中的数值的 处理方式 与 简单字符串中的数值 完全相同,并且有一些操作以原子方式递增此值。

HSET user:1000 visits 10
HINCRBY user:1000 visits 1 => 11
HINCRBY user:1000 visits 10 => 21
HDEL user:1000 visits
HINCRBY user:1000 visits 1 => 1

在这里插入图片描述
🐾hash 类型数据操作的注意事项

  • hash 类型下的 value 只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,对应的值为(nil)。
  • 每个 hash 可以存储 2^32 - 1 个键值对。
  • hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将 hash 作为对象列表使用。
  • HGETALL 操作可以获取全部属性,如果内部 field 过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈

容器型数据结构的通用规则

     list/set/hash/zset 这四种数据结构是容器型数据结构,它们共享下面两条通用规则:
(1)create if not exists
    如果容器不存在,那就创建一个,再进行操作。比如 rpush 操作刚开始是没有列表的,Redis 就会自动创建一个,然后再 rpush 进去新元素。
(2)drop if no elements
    如果容器里元素没有了,那么立即删除元素,释放内存。这意味着 lpop 操作到最后一个元素,列表就消失了。

三、Redis 通用指令

1、key 通用指令
  • 删除指定 key
del key 
  • 获取key 是否存在
exists key 
  • 获取 key 的类型
type key 
  • 为指定 key 设置有效期
 expire key seconds 
 pexpire key milliseconds 
 expireat key timestamp 
 pexpireat key milliseconds-timestamp 
  • 获取 key 的有效时间
ttl key 
pttl key 
  • 切换key从时效性转换为永久性
persist key 
  • 查询 key
 keys pattern 

查询模式规则:
在这里插入图片描述

  • 为 key 改名
rename key newkey 
renamenx key newkey 
  • 对所有 key 排序
 sort 
  • key 其他操作
 help @generic  

    key 是由程序员定义的, Redis 在使用过程中,伴随着操作数据量的增加,会出现大量的数据以及对应的 key , 数据不区分种类、类别混杂在一起,极易出现重复或冲突 。
    Redis 为每个服务提供有 16 个数据库,编号从 0 到 15,每个数据库之间的数据相互独立 。
在这里插入图片描述


2、数据库通用指令
  • 切换数据库
select index 
  • 数据移动
move key db
  • 当前数据库 key 的数量
dbsize
  • 清空当前数据库所有 key
flushdb

在这里插入图片描述

  • 清除所有数据库所有 key
flushall
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值