原理、数据类型与数据操作 (纯理论篇)
面向大数据工程技术专业 · 理论精讲
认识这位“内存极速跑者”及四大特性
会话、缓存、队列与排序
两大NoSQL巨头大比拼
掌握Redis的“收纳魔法”
在敲代码之前,先来认识它的“灵魂”
Redis 是一个开源的、基于内存运行的 Key-Value (键值对) NoSQL 数据库。
如果把我们之前学的 MySQL 数据库比作电脑的“机械硬盘”,容量大但找东西慢;
那么 Redis 就是电脑的“内存条”,容量有限,但速度快到飞起!
翻译过来就是:远程字典服务器
想象一本放在网络上的超级字典,大家都可以用极快的速度去翻阅它。
Redis 是单机性能的天花板之一。
原因:完全基于内存操作,且使用单线程避免了上下文切换的损耗。
相当于一秒钟能翻完一整本新华字典!
相比于其他简单的键值数据库(如 Memcached 只能存字符串),Redis 是一个“收纳大师”。
什么是原子性?
“原子”在物理学中意为不可再分的最小单位。在计算机中,意思是一个操作要么彻底完成,要么完全不执行,绝不会停在中间状态。
生活比喻:
就像在食堂打饭排队,队伍是单行的。一旦轮到你,阿姨给你打饭的过程是连贯的,不会有人在中途插队打断她。
假设双十一抢购,商品只剩 1 件,1000 个人同时点击“购买”。
因为 Redis 的操作是单线程排队的且具有原子性,系统绝对不会算错账把这 1 件商品卖给 2 个人(超卖现象)。
除了当数据库用,Redis 还自带了很多“插件”功能:
类似微信公众号,一个端发送消息,所有订阅的端都能立刻收到(常用于聊天室)。
虽然在内存运行,但它能定期把数据悄悄写到硬盘上,断电也不怕数据全丢。
自带 Geospatial 功能,能瞬间算出两个经纬度之间的距离(如:附近的人)。
既然这么厉害,企业都在拿它干什么?
用户登录状态需要频繁读取,存在 MySQL 太慢,存在单台服务器上又无法实现分布式共享。
就像你进入酒店办入住后拿到的房卡。你在酒店的各个设施游玩,刷房卡系统就知道是你。
大型网站有多台服务器,如果把房卡信息存在 Redis 这个统一的内存中心,用户无论访问哪台服务器,都能极速验证身份,且退出登录时能瞬间清空。
有些网页非常复杂(比如淘宝首页),要从数据库里查商品、查推荐、查价格,拼装成一个完整的网页需要很久。
解决方案: 把拼装好的整个网页 HTML 代码,或者复杂的查询结果 JSON 字符串,直接塞进 Redis。
效果: 下一个用户再访问,直接从 Redis 内存里把这个页面“端”出来,速度提升百倍!
90% 的查询请求都在 Redis 这里被拦截并直接返回了,保护了脆弱的 MySQL 数据库不被压垮。
网站注册时,经常需要发送“激活邮件”或者“短信验证码”。这种操作很慢,如果让用户在网页上干等,体验极差。
做法:
把发送邮件的任务当成一个数据,塞进 Redis 的列表(队列)里。然后立刻告诉用户“注册成功”。
后台会有另一个程序,慢慢从 Redis 队列里把任务一个个拿出来去发邮件。这就叫“异步排队”。
抖音热门视频,每秒钟可能有上千人同时点赞。
如果用关系型数据库,很容易锁死。Redis 利用其原子性的 INCR 命令,能在内存中轻松完成每秒数万次的加减法,绝不出错。
Redis 独有的 ZSet (有序集合) 数据类型,天生就是为了排行榜而生的。
例如:游戏全服战力排行榜、微博热搜榜。只要把分数和名字扔给它,它永远在底层自动帮你排好序,查询第一名和第一万名速度一样快。
Redis 不是万能的,它也有自己的“软肋”
内存非常昂贵!如果把几TB的历史聊天记录、日志文件存进Redis,老板会破产的。海量普通数据还是得靠硬盘。
Redis没有表,没有主外键。无法执行类似 MySQL 中 JOIN 这种多表相互关联的复杂查询操作。
它也是一个 NoSQL(非关系型)数据库。但它的定位是“文档型数据库”。
生活比喻:
如果说 Redis 是一个用来放高频使用物品的“桌面”,那么 MongoDB 就是一个极其灵活的大号文件柜。
在这个文件柜里,你可以随便塞各种格式的纸张(JSON文档),不需要像 MySQL 那样必须提前规划好严格的表格(Schema)。
严格的 Key-Value。
无论你存的是字符串、列表还是集合,你永远只能通过 Key 去找到这个整体的 Value。
例如:找 key="user:1" 的值。
存的是类似 JSON 的复杂文档。
文档里面可以嵌套文档、数组。而且你可以针对文档内部的某个小字段进行深度查询!
例如:查出所有“年龄大于20岁且城市在北京”的用户文档。
数据主力放在内存中。
速度极快(微秒级),但断电易失,受限于服务器的内存条容量,成本非常高昂。
数据主力存在硬盘上(通过内存映射加速)。
速度比 MySQL 快,但比 Redis 慢得多(毫秒级)。优势是能存海量数据(TB级),成本低。
开始与 Redis 对话:指令就是我们的语言
当我们在电脑上安装好客户端并连接后,第一件事应该是检查服务端是否活着,网络通不通。
这就像是在暗号对接:
127.0.0.1:6379> ping
PONG
※ 注:如果网络不通或服务未开启,这里会直接报错提示连接被拒绝。
和 MySQL 可以自由创建 CREATE DATABASE db_name 不同,Redis 库是固定且预先创建好的。
用于在不同的数据库之间切换。
语法: SELECT 编号
不管数据存的是什么格式,Redis 永远是通过 Key 来找数据的。因此对 Key 的操作是基础中的基础。
命令: KEYS *
作用:列出当前库里的所有键名字。
⚠️ 警告:企业生产环境中严禁使用该命令!数据量大时会导致 Redis 假死(因为它是单线程排队的)。
命令: EXISTS 键名
作用:如果存在返回1,不存在返回0。
这个命令非常常用,在查询前先判断一下有没有这个数据,防止报错。
命令: DEL 键名
作用:将指定的 Key 连同它的 Value 一起从内存中彻底删除。如果删除成功返回1,不存在返回0。
命令: TYPE 键名
作用:由于 Redis 里的值有五大类型,当我们忘记某个键存的是什么格式时,可以用此命令探测(返回 string, list, set, zset 或 hash)。
既然 Redis 是当“缓存”用的,而内存是有限的,就不能让数据永远占着茅坑不拉屎。必须给数据设定生命周期。
EXPIRE 键名 秒数
给已经存在的 Key 设置一个倒计时,时间一到,Redis 会自动把它“杀死”(删除)。
TTL 键名
TTL = Time To Live。返回剩余存活的秒数。
手机验证码
收到短信验证码提示“5分钟内有效”,底层其实就是执行了 EXPIRE code 300。
Redis 的“收纳魔法”:五大经典数据结构
String, Hash, List, Set, ZSet
注意:所谓的“类型”,其实都是指 Value(值) 的类型,Key 永远是字符串!
字符串
哈希/对象
列表/队列
无序集合
有序集合
String 是 Redis 最基础、最常用 的数据类型。
语法: SET key value
如果 Key 已经存在,则会覆盖原来的值。
语法: GET key
如果 Key 不存在,则返回 nil(表示空)。
嫌一条条写太慢?使用 M (Multiple) 指令。
MSET k1 v1 k2 v2MGET k1 k2 k3一次网络请求搞定多个数据,极大地提升效率。
如果字符串里存的是纯数字,可以使用自增命令。
INCR key:数值加 1DECR key:数值减 1这就是前面提到的“原子操作”,高并发下绝对不会算错(比如1000个人同时点赞)!
把数据库中查询出来的文章详情、商品信息转成 JSON 字符串,存入 Redis。下次用户访问直接从内存读,极大减轻 MySQL 压力。
利用 INCR 命令。比如贴吧的帖子浏览量、点赞数、或者限制某个API的一分钟访问次数(防刷防爬虫)。
将手机号作为 Key,验证码作为 Value,配合 EXPIRE 设置 5 分钟过期时间,实现完美闭环。
如果说 String 是一个装了一样东西的纸盒子,那 Hash 就是一个带有很多抽屉的文件夹。
| 字段 (Field) | 值 (Value) |
|---|---|
| name | "张三" |
| age | 20 |
| city | "北京" |
在指定的哈希表里操作具体字段。
HSET key field valueHGET key field一次性取出全部字段和值,或删除指定字段。
HGETALL keyHDEL key fieldList 是一个简单的字符串列表,按照插入顺序排序。
[ L : 左端 ] [ R : 右端 ]
想象排队买票:有人从前面插队,有人从后面排队。
LPUSH key value:从左侧(头部)塞入RPUSH key value:从右侧(尾部)塞入LPOP key:从左侧吐出一个并删除RPOP key:从右侧吐出一个并删除注意:POP操作就像把球拿走了,管子里就没这个球了!如果管子空了,连 Key 都会被系统自动删除。
如果我只想看看管子里有哪些数据,不拿走怎么办?
LRANGE key start stopLRANGE key 0 -1注:-1 代表列表的最后一个元素。
利用一头进、另一头出的特性(FIFO 先进先出),非常适合处理前面提到过的发送邮件任务排队。
利用 LPUSH 将最新的文章ID推入列表头部,用户总是使用 LRANGE 0 9 获取最新的10条动态(朋友圈、微博时间线)。
你往里面扔相同的乒乓球,它会自动帮你把重复的变消失,保证桶里的每一个球都是独一无二的。且球在里面是打乱的,没有先后顺序。
SADD key value1 value2:往集合里加元素。如果加了重复的,会被自动忽略。SMEMBERS key:查看集合里所有的元素(查出来的顺序可能是乱的)。SISMEMBER key value:判断某元素是否在集合内。存在返回1,不存在返回0。这个命令速度极快,不管桶里有十万还是百万个球,瞬间就能告诉你某个球在不在里面。
给用户打标签。一个用户不能有同一个标签两次。
例如:张三被打了 "程序员", "宅男", "游戏迷" 标签。用 Set 的去重特性来存再合适不过。
Set 支持强大的数学集合运算!
SINTER (交集) 命令,瞬间算出他们的共同好友是 B, C。ZSet 全称 Sorted Set,是 Redis 中最特殊、也最有魅力的类型之一。
内部永远保持按 Score 自动排序
ZADD key score memberZRANGE key start stop (从小到大排)ZREVRANGE key start stop (从大到小排,Reverse)例如:获取前三名,使用 ZREVRANGE rank 0 2 即可。
• 微博热搜榜:将热度值作为 Score,话题作为 Member。
• 直播间送礼榜:将刷礼物的金额作为 Score,用户ID作为 Member。
• 学生成绩排名:将考试分数作为 Score,学号作为 Member。
感谢大家的聆听
🚀 下节实验课预告:我们将进入机房,在电脑上实战敲击今天学过的所有命令!