黑马程序员Redis课程笔记
基础篇
NoSQL
分类
-
键值类型(Redis)
-
文档类型(MongoDB)
-
列类型(HBase)
-
Graph类型(Neo4j)
与SQL区别
| ---------- | SQL | NoSQL |
|---|---|---|
| 数据结构 | 结构化 | 非结构化 |
| 数据关联 | 关联的 | 无关联 |
| 查询方式 | SQL查询 | 非SQL |
| 事务特性 | ACID | BASE |
| 存储方式 | 磁盘 | 内存 |
| 拓展性 | 垂直 | 水平 |
| 使用场景 | 数据结构固定,对数据安全性要求高 | 数据结构结构不固定,安全性要求不高,对性能有要求 |
Redis
Redis诞生于2009年全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。
特征
-
键值(key-value)型,value支持多种不同数据结构,功能丰富
-
单线程,每个命令具备原子性
-
低延迟,速度快(基于内存、O多路复用、良好的编码)
-
支持数据持久化支持主从集群、分片集群
-
支持多语言客户端
数据结构
Redis是典型的key-value数据库,key一般是字符串,而value包含很多不同的数据类型。
| 数据类型 | 示例 |
|---|---|
String |
hello world |
Hash |
{“name”:“Jack”,“age”:21} |
List |
[A->B->C->C] |
Set |
{A,B,C} |
SortedSet |
{A:1,B:2,C:3] |
GEO |
{A:(120.3,30.5)] |
BitMap |
0110110101110101011 |
HyperLog |
0110110101110101011 |
命令
键管理
| 命令 | 语法示例 | 说明 |
|---|---|---|
DEL |
DEL key1 key2 | 删除一个或多个键。 |
EXISTS |
EXISTS key | 检查键是否存在(返回 1 或 0)。 |
EXPIRE |
EXPIRE key 60 | 设置键的过期时间(秒)。 |
TTL |
TTL key | 查看键的剩余生存时间(秒,-1 表示永久,-2 表示已过期)。 |
KEYS |
KEYS pattern* | 查找匹配模式的键(生产环境慎用,可能阻塞)。 |
字符串
value是字符串,根据字符串的格式不同分为3类:
-
string:普通字符串,例如 hello world -
int:整数类型,可以做自增、自减操作,例如 10 -
float:浮点类型,可以做自增、自减操作,例如 92.5
底层都以字节数组形式存储,最大空间不超过512m。
| 命令 | 语法示例 | 说明 |
|---|---|---|
SET |
SET key value | 设置键值对,可覆盖之前的值 |
GET |
GET key | 获取键的值。 |
INCR |
INCR key | 将键的值递增 1(原子操作)。 |
MSET |
MSET k1 v1 k2 v2 | 批量设置多个键值对。 |
MGET |
MGET k1 k2 | 根据多个key获取多个String类型的value |
SETNX |
SETNX newkey value | 添加一个String类型的键值对,前提是这个key不存在,否则不执行 |
SETEX |
SETEX key seconds value | 添加一个String类型的键值对,并指定有效期 |
Key的层级形式
Redis的key允许有多个单词形成层级结构,多个单词之间用:隔开,格式如下:
-
项目名:业务名:类型:id
格式也可以根据需求修改。例如如果项目名叫program,有user和product两种不同类型的数据,我们可以这样定义key:
-
user相关的key:
program:user:1 -
product相关的key:
program:product:1
如果value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储
| KEY | VALUE |
|---|---|
| program:user:1 | {“id”:1, “name”: “Ryo”, “age”: 21} |
| program:product:1 | {“id”:1, “name”: “咖啡”, “price”: 19} |
Hash类型
-
Hash类型,也叫散列,其中value是一个无序字典,类似于Java中的HashMap结构
-
String结构是将对象序列化为JSON字符串后存储,不方便修改对象的某个属性值
-
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD
| KEY | field | value |
|---|---|---|
| program:user:1 | name | Ryo |
| age | 21 | |
| program:user:2 | name | Tsugu |
| age | 18 |
Hash的常见命令:
| 命令 | 语法示例 | 说明 |
|---|---|---|
HSET |
HSET key field value | 添加或者修改hash类型key的field的值 |
HGET |
HGET key field | 获取一个hash类型key的field的值 |
HMSET |
HMSET key field1 value1 field2 value2 | 批量添加多个hash类型key的field的值 |
HMGET |
HMGET key field1 field2 | 批量获取多个hash类型key的field的值 |
HGETALL |
HGETALL key | 获取一个hash类型的key中的所有的field和value |
HKEYS |
HKEYS key | 获取一个hash类型的key中的所有的field |
HVALS |
HVALS key | 获取一个hash类型的key中的所有的value |
HINCRBY |
HINCRBY key field increment | 让一个hash类型key的字段值自增并指定步长 |
HSETNX |
HSETNX key field value | 添加一个hash类型的key的field值,前提是这个field不存在,否则不执行 |
List类型
Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。特征也与LinkedList类似:
-
有序
-
元素可以重复
-
插入和删除快
-
查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
| 命令 | 语法示例 | 说明 |
|---|---|---|
LPUSH |
LPUSH key element1 element2 | 向列表左侧插入一个或多个元素 |
LPOP |
LPOP key | 移除并返回列表左侧的第一个元素,没有则返回 nil |
RPUSH |
RPUSH key element1 element2 | 向列表右侧插入一个或多个元素 |
RPOP |
RPOP key | 移除并返回列表右侧的第一个元素 |
LRANGE |
LRANGE key start end | 返回列表中指定下标范围内的所有元素(支持负数下标,如 -1 表示末尾) |
BLPOP |
BLPOP key1 key2 timeout | 阻塞式移除并返回列表左侧第一个元素,无元素时等待指定时间(秒) |
BRPOP |
BRPOP key1 key2 timeout | 阻塞式移除并返回列表右侧第一个元素,无元素时等待指定时间(秒) |
Set类型
Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:
-
无序
-
元素不可重复
-
查找快
-
支持交集、并集、差集等功能
| 命令 | 语法示例 | 说明 |
|---|---|---|
SADD |
SADD key member1 member2 | 向集合中添加一个或多个元素 |
SREM |
SREM key member1 member2 | 从集合中移除一个或多个指定元素 |
SCARD |
SCARD key | 返回集合中元素的数量(基数) |
SISMEMBER |
SISMEMBER key member | 判断指定元素是否是集合的成员 |
SMEMBERS |
SMEMBERS key | 获取集合中的所有元素 |
SINTER |
SINTER key1 key2 | 返回多个集合的交集 |
SDIFF |
SDIFF key1 key2 | 返回第一个集合与其他集合的差集 |
SUNION |
SUNION key1 key2 | 返回多个集合的并集 |
SortedSet类型
Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。
SortedSet具备下列特性:
-
可排序
-
元素不重复
-
查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
| 命令 | 语法示例 | 说明 |
|---|---|---|
ZADD |
ZADD key score1 member1 [score2 member2] | 添加一个或多个元素到有序集合,若已存在则更新其score |
ZREM |
ZREM key member1 [member2] | 删除有序集合中的一个或多个指定元素 |
ZSCORE |
ZSCORE key member | 获取有序集合中指定元素的分数 |
ZRANK |
ZRANK key member | 获取指定元素的排名(按分数升序,从 0 开始) |
ZREVRANK |
ZREVRANK key member | 获取指定元素的排名(按分数降序,从 0 开始) |
ZCARD |
ZCARD key | 获取有序集合的元素个数 |
ZCOUNT |
ZCOUNT key min max | 统计分数在范围内的元素数量 |
ZINCRBY |
ZINCRBY key increment member | 指定元素自增,步长为指定的increment值 |
ZRANGE |
ZRANGE key start stop | 按分数升序返回排名在范围之间的元素 |
ZREVRANGE |
ZREVRANGE key start stop | 按分数降序返回排名在范围之间的元素 |
ZRANGEBYSCORE |
ZRANGEBYSCORE key min max | 返回分数在范围之间的元素(升序) |
ZDIFF |
ZDIFF numkeys key1 key2 | 计算多个有序集合的差集 |
ZINTER |
ZINTER numkeys key1 key2 | 计算多个有序集合的交集 |
ZUNION |
ZUNION numkeys key1 key2 | 计算多个有序集合的并集 |
Redis的Java客户端
目前主流的Redis的Java客户端:
-
Jedis:以Redis命令作为方法名称,学习成本低,简单实用。但是Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用。
-
Lettuce:基于Netty实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持Redis的哨兵模式、集群模式和管道模式。
-
Redisson:基于Redis实现的分布式、可伸缩的Java数据结构集合。包含诸如Map、Queue、Lock、Semaphore、AtomicLong等强大功能。
Jedis
在maven中引入依赖:
1 | <!--jedis--> |
创建单元测试:
1 | private Jedis jedis; |
Jedis连接池
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,推荐使用Jedis连接池代替直连方式。
首先在main文件夹下创建一个工具类:
1 | public class JedisConnectionFactory { |
随后可以在单元测试中使用:
1 | jedis = JedisConnectionFactory.getJedis(); |
SpringDataRedis
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis。
-
提供了对不同Redis客户端的整合(Lettuce和Jedis)
-
提供了RedisTemplate统一API来操作Redis
-
支持Redis的发布订阅模型
-
支持Redis哨兵和Redis集群
-
支持基于Lettuce的响应式编程
-
支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
-
支持基于Redis的JDKCollection实现
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中。
| API | 返回值类型 | 说明 |
|---|---|---|
redisTemplate.opsForValue() |
ValueOperations | 操作String类型数据 |
redisTemplate.opsForHash() |
HashOperations | 操作Hash类型数据 |
redisTemplate.opsForList() |
ListOperations | 操作List类型数据 |
redisTemplate.opsForSet() |
SetOperations | 操作Set类型数据 |
redisTemplate.opsForzSet() |
ZSetOperations | 操作SortedSet类型数据 |
redisTemplate |
通用的命令 |
-
在maven中引入依赖:
1 | <dependency> |
-
配置文件:
1 | spring: |
-
编写测试
1 | @Autowired |
RedisTemplate写入前会把Object序列化为字节形式,默认是采用JDK序列化,例如:
1 | 127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x04NAME" |
可以自定义RedisTemplate的序列化方式
- 本文链接:https://squirrelune.github.io/cn/Redis%E7%AC%94%E8%AE%B0/Redis%E7%AC%94%E8%AE%B001/
- 许可协议: 除特殊声明外,本站博文均采用 CC BY-NC-SA 3.0 CN 许可协议,转载请注明出处!