Redis基础篇
认识 NoSQL
NoSQL,非关系型数据库,它们不保证关系型数据库的ACID特性(原子性、一致性、隔离性、持久性)。NoSQL概念在2009年被提出来,NoSQL最常见的解释是“non-relational”,"No noly SQL"也被很多人接受。NoSQL被我们用来最多的当作 key - value存储,当然还有其他文档型的、列存储、图型数据库、XML数据库等。
NoSQL与SQL的对比
1. SQL具有结构化,NoSQL不具有结构化
意思:
SQL的结构化是固定的,以表的形式存储,允许添加约束。
NoSQL的结构化是多变的,可以使用键值对的形式(key,value),也可以通过 文本的形式(Document),还可以通过图的形式(Graph)

2. SQL具有关联性,而NoSQL不具有关联性
SQL:可以通过外键的形式,来确定哪个用户买了商品
NoSQL:由于NoSQL不具有关联性,所有一般使用 Json 的格式,来确定用户购买哪些商品
SQL:

NoSQL:

3. SQL具有大部分固定的 SQL 查询语法,而 NoSQL 的查询语句都不相同
比如:
1 -- SQL 中查询时语法
2 SELECT * FROM TBL_USER WHERE ID = 1;
3
4 -- NoSQL中的查询根据数据库的不同分为几种。
5 -- Redis:
6 get user:1
7 --MongDB:
8 db.users.find({_id:1})
4. SQL的事务支持ACID,NoSQL的事务仅仅只能满足基本的事务功能

总结
| SQL | NOSQL | |
| 数据结构化 | 结构化 | 非结构化 |
| 数据关联 | 无关联的 | 无关联 |
| 事务特性 | ACID | 非SQL |
| 存储方式 | 磁盘 | 内存 |
| 扩展性 | 垂直 | 水平 |
| 使用场景 |
1)数据结构固定 2)相关业务对数据安全性、一致性要求高 |
1)数据结构不固定 2)对一致性、安全性要求不高 3)对性能要求高 |
Redis
redis就是一个非关系型数据库,Redis的特点
1️⃣键值型,value 支持多种不同的数据结构,功能丰富
2️⃣单线程,每个命令具有原子性
3️⃣低延迟,速度快(基于内存、IO 多路复用、良好的编码)
4️⃣支持数据持久化
5️⃣支持主从集群、分片集群
6️⃣支持多语言客户端
这里讲了Redis的厉害之处,后面将简单讲解一下 Redis 的基本数据结构及其命令
Redis命令
Redis是一个 key-value 的数据库,key一般是 String 类型,不过 value 的类型多种多样。
1 String:hello world(字符串)
2 Hash:{name: "Jack", age: 21}(哈希)
3 List:[A -> B -> C -> D] (有序集合, 可以重复)
4 Set:{A, B, C}(无序集合, 不能重复的)
5 SortedSet(ZSET):{A: 1, B: 2, C: 3}(可排序的集合)
6 GEO:{A: (120.3, 30.5)}(坐标)
7 BitMap:01101101110101011
8 HyperLog: 01101101110101011
注意: 1~5属于基本类型、6~8属于特殊类型
图片如下:

学习Redis时,命令不记得没太大关系,但是要学会自己查看命令,查看命令的方式:
通过 help命令查看:

通过官方文档进行查看:

Redis通用命令
1. KEYS:查看符合模板的所有key,不建议再生产环境设备上使用,可以搭配 通配符 进行使用

2. DEL:删除一个指定的 key (返回 1 代表删除成功)

3. EXISTS:判断 key 是否存在(1代表存在, 0代表不存在)

4. EXPIRE: 给一个 key 设置有效期,有效期到,该 key 会被自动删除

5. TTL:查看一个 key 的剩余有效期(-2代表已过期)

注意:
一开始设置的key,如果没有指定 ttl 过期时间,默认为 -1 代表永久

String 类型
String 类型,就是 字符串类型,是 Redis 中最简单的存储类型。
其 value 是字符串,不过根据字符串格式不同,分为 3类
1️⃣String:普通字符串
2️⃣int:整数类型,可以做自增、自减操作
3️⃣float:浮点类型,可以做自增、自减操作
注意:字符串类型的最大空间不能超过 512m
- String:普通字符串
- int:整数类型,可以做自增、自减操作
- float:浮点类型,可以做自增、自减操作
不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。
String常见命令
1️⃣设置种类 key 的命令:
1. SET:添加或者修改已存在的一个 String 类型的键值对
如果设置的key重名时,则进行替换

2. MSET:批量添加多个 String 类型的 value

3. SETNX:添加一个 Stirng 类型的键值对,前提是这个 key 不存在,否则不执行

注意:
①这个 setnx k1 123 为什么会返回0 执行不成功呢?
-- 可以看到上面的命令,k1 是存在的,所以添加失败,返回0
get k1
② SETNX = SET NX 这两个命令效果是一致的
4. SETEX:添加一个 String 类型的键值对,并且指定有效期
语法:SETEX key 秒 value

注意:
SETEX = SET EX (SETEX 命令 与 SET 命令 EX 参数效果一致)
2️⃣获取key的命令:
1. GET:根据 key 获取 String 类型的 value

2. MGET:批量获取多个 key 对应的 value 值

3️⃣功能型,自增、自减的命令:
1. INCR:让一个整形的 key 自增 1

2. INCRBY:让一个整形的 key 自增指定的步长
例如:incrby num 2:让 num 值自增2

注意:
这个数字不一定要 正数 ,如果为 负数 则表示自减指定步长

5. INCRBYFLOAT:让一个浮点类型的数字 自增 并指定步长
同理:也可以是负数

思考
Redis 并没有类似 MySQL 中的 Table 概念,我们要如何进行区分不同类型的 key 呢?
场景:需要存储用户、商品信息到 Redis中,有一个用户的id为1,有一个商品id恰好也是1,要怎么办?
答案/解决方案:
Redis的key允许有多个单词进行层级结构,多个单词之间用 ":" 隔开(这个可以按照公司的要求来),格式如下:
项目名:业务名:类型id
例子:
- user相关的key:gzyhrc:user:1
- product相关的key:gzyhrc:product:1
Hash类型
Hash类型,是无序字段,类似于 HashMap结构
String 类型 与 Hash 类型比较
- String 类型,如果存储的内容为 json 格式,也仅仅是一个字符串存储起来,这样就导致,如果我相对 json 格式存储 某个 属性进行修改时,只能删除后重新填写。
- Hash 类型,对于 json 格式的数据,可以指定某个属性,并对他进行直接操作,无需这样复杂的操作,对每单个字段都可以进行 CRUD 操作。
Hash常见命令
1️⃣设置 Hash类型key的field的值
1. HSET key filed value:单个添加或者修改 hash类型的 field 的值

2. HMSET key field value [field value]:批量添加多个 hash 类型 key 的field 的值

3. HSETNX key field value:添加一个 hash类型 key 的 field 值,前提是这个field不存在,否则不执行

2️⃣获取key的filed值
1. HGET key field:获取一个 hash 类型 key 的field 的值

2. HMGET key field [field]:批量获取多个 hash 类型 key的field 的值

3. HGETALL key:获取一个 hash 类型的 key 中所有的 field value

4. HKEYS key:获取一个 hash类型的key中的所有的field

5. HVALS key:获取一个 hash类型的key中的所有value

3️⃣功能性自增、自减命令:
1. HINCRBY key field increment:让一个hash类型的key的field 值 自增并指定步长
注意:如果指定步长为负数,则自减

List类型
概念:Redis中的List类型与Java中的LinkedList类似,可以看做时一个双向链表结构,既可以支持正向检索和也可以反向检索。
特征与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一版
- 常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
List常见命令
1️⃣设置元素命令:
1. LPUSH key element ........:向列表左侧插入一个或多个元素

2. RPUSH key element:向列表右侧插入一个或多个元素

2️⃣获取元素命令:
1. LPOP key:移除并返回列表左侧的第一个元素,没有返回 nuil

2. RPOP key:移除并返回列表右侧的第一个元素,没有则返回nuil

3. LRANGE key start end:返回一段索引范围内容的所有元素

4. BLPOP 和 BRPOP:与LPOP 和 RPOP类似,只不过在没有元素时候等待指定时间,而不是直接返回null

思考
1. 如何利用 List 结构模拟出一个栈?
答案:只需要考虑,入口和出口 在同一边即可,意思:要么都用 lpush/lpop,要么都用 rpush/rpop
2. 如何利用 List 结构模拟出一个队列?
答案:只需要考虑,入口和出口 不同一边即可,意思:要么 lpush/rpop,要么 rpush/lpop
3. 如何利用 List 结构 模拟一个阻塞队列?
- 队列要求:入口和出口不同边
- 阻塞要求:出队时采用 BLPOP 和 BRPOP
SET 类型
Redis 的 Set 结构与 Java中的 HashSet 类似,可以看做是一个 value 为 null 的 HashMap。
特点:
- 无序
- 元素不可重复
- 查找快
- 支持交集、并集、差集等功能,适合于:发现好友列表等场景
Set常见命令
1️⃣设置元素命令:
1. SADD key member ......:向 set中添加一个或者多个元素

2️⃣获取元素命令:
2. SREM key member .....:移除 set 中的指定元素

3️⃣判断元素是否存在于set中:
3. SISMEMBER key member .....:判断一个元素是否存在于 set 中
如果不存在,则返回0

4️⃣返回set中元素的个数:
4. SCARD key:返回set 中元素的个数

5️⃣获取key1和key2 的交集:
5. SINTER key1 key2 ....:求出key1 和 key2 的交集

6️⃣获取key1与key2的差集:
6. SDIFF key1 key2 .....:求出key1 和 key2 的差集

注意:如果 hrc:set:2在前面,即拿 hrc:set:2 的差集

7️⃣:求获取key1和key2的并集
7. SUNION key1 key2......

练习题
前提:将下列的数据用Redis的Set集合来存储:
- 张三的好友有:李四、王五、赵六
- 李四的好友有:王五、麻子、二狗
1 -- 张三好友有:李四、王五、赵六
2 sadd zs lisi wangwu zhaoliu
3 -- 李四好友有:王五、麻子、二狗
4 sadd ls wangwu mazi ergou
利用Set的命令实现下面的功能:
1. 计算张三好友个数
scard zs
2. 计算张三和李四有哪些共同好友
sinter zs ls
3. 查询哪些人是张三的好友却不是李四的好友
sdiff zs ls
4. 查询张三和李四的好友总共有哪些人
sunoin zs ls
5. 判断李四是否是张三的好友
sismember zs lisi
6. 判断张三是否是李四的好友
sismember ls zhangsan
7. 将李四从张三的好友列表中移除
srem zs lisi
SortedSet类型
Redis 的 SortedSet 是一个可排序的 set 集合,与Java中的 TreeSet 有些类似,但底层数据结构差别很大。SortedSet中的每一个元素都带一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表
SortedSet具有下列特性:
- 可排序,经常用于实现排行榜这样的功能
- 元素不重复
- 查询速度快
SortedSet常见命令
1. ZADD key score member :添加一个或多个元素倒 sorted set,如果已经存在则更新其score值

2. ZREM key member:删除 sorted set中的一个指定元素

3. ZSCORE key member:获取 sorted set 中的指定元素的score值

4. ZRANK key member:获取sorted set 中指定元素的排名

5. ZCARD key:获取sorted set 中的元素个数

6. ZCOUNT key min max:统计 score 值在给定范围内的所有元素的个数
举个例子:判断score 值的给定的 [0,1]范围内的值,只有一个app

7. ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的increment值
举个例子:app的score值,从1变成 2.5

8. ZRANGE key min max:按照score排序后,获取指定排名范围内的元素
举个例子:查询出第三名、第四名、第五名的元素,由于这里没有第五个元素,所有返回只有两个元素
注意:
下标是根据0开始算起的

9. ZRANGEBYSCORE key min max:按照score 排序后,获取指定score范围内容的元素
举个例子:查询介于分数在2~4之间的元素

10. 求差集、交集、并集
差集
ZDIFF 命令用于计算多个有序集合的差集,即返回存在于第一个集合但不存在于其他集合中的元素。
语法:ZDIFF numkeys key [key ...] [WITHSCORES]
- numkeys:参与计算的集合数量
- key:有序集合的键名
- withscores:可选参数,表示是否返回元素的分数
交集
ZINTER 命令用于计算多个有序集合的交集,并可以指定聚合方式(如求和、最小值、最大值)
语法:ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
- destination:存储结果的键名
- numkeys:参与计算的集合数量
- key:有序集合的键名
- weights:可选参数,为每个集合指定权重
- aggregate:可选参数,指定集合方式(sum、min、max)
并集
ZUNION 命令用于计算多个有序集合的并集,并可以指定聚合方式(如求和、最小值、最大值)
语法:
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
- destination:存储结果的键名
- numkeys:参与计算的集合数量
- key:有序集合的键名
- weights:可选参数,为每个集合指定权重
- aggregate:可选参数,指定集合方式(sum、min、max)
SortedSet的练习
将班级的下列学生得分存入Redis的SortedSet中:
Jack 85,Lucy 89,Rose 82,Tom 95,Jerry 78,Amy 92,Miles 76
zadd score Jack 85 Lucy 89 Rose 82 Tom 95 Jerry 78 Amy 92 Miles 76
练习一:删除Tom同学
zrem score Tom
练习二:获取Amy同学的分数
zscore score Amy
练习三:获取Rose同学的排名
排名第三名,因为从0开始排
zrank score Rose
降序的方式:
ZREVRANK score Rose
练习四:查询80分一下有几个同学
zcount score 0 80
练习五:给Amy同学加 2分
zincrby score 2 Amy
练习六:查出成绩前3名的同学
由于排名按照0开始算起的
zrange score 0 2
练习七:查出成绩80分一下的所有同学
zrangebyscore score 0 80

浙公网安备 33010602011771号