1. 安装 Redis
1.1 安装
# Redis 是 c 语言编写,需要安装依赖库yum install -y gcc tcl# 上传压缩包后解压tar -xzf redis-6.2.6.tar.gz# 进入 Redis 目录cd redis-6.2.6# 编译安装make && make install
1.2 启动
1.2.1 指定配置文件启动
# 允许访问的地址,默认是 127.0.0.1,会导致只能在本地访问。修改为 0.0.0.0 则可以在任意 IP 访问bind 0.0.0.0# 守护进程,修改为yes后即可后台运行daemonize yes# 密码,设置后访问 Redis 必须输入密码requirepass 123321# 监听的端口port 6379# 工作目录,默认是当前目录,也就是运行 redis-server 时的命令,日志、持久化等文件会保存在这个目录dir .# 数据库数量,设置为 1,代表只使用 1 个库,默认有 16 个库,编号 0~15databases 1# 设置 redis 能够使用的最大内存maxmemory 512mb# 日志文件,默认为空,不记录日志,可以指定日志文件名logfile "redis.log"
# 启动redis-server redis.conf
1.2.2 开机自启
# 新建一个系统服务文件,文件内容见下方vi /etc/systemd/system/redis.service# 重载系统服务systemctl daemon-reload
[Unit]Description=redis-serverAfter=network.target[Service]Type=forkingExecStart=/usr/local/bin/redis-server /usr/local/redis-6.2.6/redis.confPrivateTmp=true[Install]WantedBy=multi-user.target
# 启动systemctl start redis# 停止systemctl stop redis# 重启systemctl restart redis# 查看状态systemctl status redis
2. Redis 常见命令
2.1 通用命令
通用指令是部分数据类型的,都可以使用的指令,常见的有:
KEYS:查看符合模板的所有 keyDEL:删除一个指定的 keyEXISTS:判断 key 是否存在EXPIRE:给一个 key 设置有效期,有效期到期时该 key 会被自动删除TTL:查看一个KEY的剩余有效期
2.2 String 类型
String 类型,也就是字符串类型,是 Redis 中最简单的存储类型。其 value 是字符串,不过根据字符串的格式不同,又可以分为3类:
- string:普通字符串
- int:整数类型,可以做自增、自减操作
- float:浮点类型,可以做自增、自减操作
不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过 512m
SET:添加或者修改已经存在的一个 String 类型的键值对GET:根据 key 获取 String 类型的 valueMSET:批量添加多个String类型的键值对MGET:根据多个 key 获取多个 String 类型的 valueINCR:让一个整型的 key 自增 1INCRBY:让一个整型的 key 自增并指定步长,例如:incrby num 2 让 num 值自增 2INCRBYFLOAT:让一个浮点类型的数字自增并指定步长SETNX:添加一个 String 类型的键值对,前提是这个 key 不存在,否则不执行SETEX:添加一个 String 类型的键值对,并且指定有效期
2.3 Hash 类型
Hash 类型,也叫散列,其 value 是一个无序字典,类似于 Java 中的 HashMap 结构
String 结构是将对象序列化为 JSON 字符串后存储,当需要修改对象某个字段时很不方便
Hash 结构可以将对象中的每个字段独立存储,可以针对单个字段做 CRUD
HSET key field value:添加或者修改 hash 类型 key 的 field 的值HGET key field:获取一个 hash 类型 key 的 field 的值HMSET:批量添加多个 hash 类型 key 的 field 的值HMGET:批量获取多个 hash 类型 key 的 field 的值HGETALL:获取一个 hash 类型的 key 中的所有的 field 和 valueHKEYS:获取一个 hash 类型的 key 中的所有的 fieldHVALS:获取一个 hash 类型的 key 中的所有的 valueHINCRBY:让一个 hash 类型 key 的字段值自增并指定步长HSETNX:添加一个 hash 类型的 key 的 field 值,前提是这个 field 不存在,否则不执
2.4 List 类型
Redis 中的 List 类型与 Java 中的 LinkedList 类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索,特征也与 LinkedList 类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等
LPUSH key element ... :向列表左侧插入一个或多个元素LPOP key:移除并返回列表左侧的第一个元素,没有则返回 nilRPUSH key element ... :向列表右侧插入一个或多个元素RPOP key:移除并返回列表右侧的第一个元素LRANGE key star end:返回一段角标范围内的所有元素BLPOP 和 BRPOP:与 LPOP 和 RPOP 类似,只不过在没有元素时等待指定时间,而不是直接返回 nil
如何利用 List 结构模拟一个栈
- 入口和出口在同一边
如何利用 List 结构模拟一个队列
- 入口和出口在不同边
如何利用 List 结构模拟一个阻塞队列
- 入口和出口在不同边出队时
-
2.5 Set 类型
Redis 的 Set 结构与 Java 中的 HashSet 类似,可以看做是一个 value 为 null 的 HashMap。因为也是一个 hash 表,因此具备与 HashSet 类似的特征:
无序
- 元素不可重复
- 查找快
- 支持交集、并集、差集等功能 ``` SADD key member … :向 set 中添加一个或多个元素
SREM key member … : 移除 set 中的指定元素
SCARD key: 返回 set 中元素的个数
SISMEMBER key member:判断一个元素是否存在于 set 中
SMEMBERS:获取 set 中的所有元素
SINTER key1 key2 … :求 key1 与 key2 的交集
SDIFF key1 key2 … :求 key1 与 key2 的差集
SUNION key1 key2 ..:求 key1 和 key2 的并集
<a name="WukA4"></a>## 2.6 SortedSet 类型Redis 的 SortedSet 是一个可排序的set集合,与 Java 中的 TreeSet 有些类似,但底层数据结构却差别很大。SortedSet 中的每一个元素都带有一个 score 属性,可以基于 score 属性对元素排序,底层的实现是一个跳表(SkipList)+ hash 表。SortedSet 具备下列特性:- 可排序- 元素不重复- 查询速度快- 因为 SortedSet 的可排序特性,经常被用来实现排行榜这样的功能
ZADD key score member:添加一个或多个元素到 sorted set ,如果已经存在则更新其 score 值
ZREM key member:删除 sorted set 中的一个指定元素
ZSCORE key member : 获取 sorted set 中的指定元素的 score 值
ZRANK key member:获取 sorted set 中的指定元素的排名
ZCARD key:获取 sorted set 中的元素个数
ZCOUNT key min max:统计 score 值在给定范围内的所有元素的个数
ZINCRBY key increment member:让 sorted set 中的指定元素自增,步长为指定的 increment 值
ZRANGE key min max:按照 score 排序后,获取指定排名范围内的元素
ZRANGEBYSCORE key min max:按照 score 排序后,获取指定 score 范围内的元素
ZDIFF、ZINTER、ZUNION:求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的 Z 后面添加 REV 即可
<a name="yA3zb"></a># 3. SpringDataRedis<a name="P48mM"></a>## 3.1 介绍SpringData 是 Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 的集成模块就叫做 SpringDataRedis,官网地址是[https://spring.io/projects/spring-data-redis](https://spring.io/projects/spring-data-redis)- 提供了对不同 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** | | 通用的命令 |<a name="XylVM"></a>## 3.2 序列化方式<a name="oWmgF"></a>### 3.2.1 JDK 序列化方式因为默认使用的 `JdkSerializationRedisSerializer`序列化方式,所以这里的 key 和 value 都变成了如下格式```java@Data@NoArgsConstructor@AllArgsConstructorpublic class User implements Serializable {private Long id;private String name;}
@SpringBootApplicationpublic class SpringDataRedisApplication implements ApplicationRunner {@Autowiredprivate RedisTemplate redisTemplate;public static void main(String[] args) {SpringApplication.run(SpringDataRedisApplication.class, args);}@Overridepublic void run(ApplicationArguments args) throws Exception {// 存储字符串对象redisTemplate.opsForValue().set("name", "张三");System.out.println(redisTemplate.opsForValue().get("name"));// 存储实体类型redisTemplate.opsForValue().set("user:1", new User(1L, "张三"));System.out.println(redisTemplate.opsForValue().get("user:1"));}}
127.0.0.1:6379> keys *1) "\xac\xed\x00\x05t\x00\x06user:1"2) "\xac\xed\x00\x05t\x00\x04name"127.0.0.1:6379> get \xac\xed\x00\x05t\x00\x04name(nil)127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x04name""\xac\xed\x00\x05t\x00\x06\xe5\xbc\xa0\xe4\xb8\x89"127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x06user:1""\xac\xed\x00\x05sr\x009org.masteryourself.tutorial.spring.data.redis.entity.User,&\xf2t\x9f\x94\xc3)\x02\x00\x02L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\x04namet\x00\x12Ljava/lang/String;xpsr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x01t\x00\x06\xe5\xbc\xa0\xe4\xb8\x89"
3.2.2 指定序列化格式
为了在反序列化时知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,存入 Redis,会带来额外的内存开销
@Configurationpublic class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {// 创建TemplateRedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// 设置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);// 设置序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// key 和 hashKey 采用 string 序列化redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());// value 和 hashValue采用 JSON 序列化redisTemplate.setValueSerializer(jsonRedisSerializer);redisTemplate.setHashValueSerializer(jsonRedisSerializer);return redisTemplate;}}
@SpringBootApplicationpublic class SpringDataRedisApplication implements ApplicationRunner {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public static void main(String[] args) {SpringApplication.run(SpringDataRedisApplication.class, args);}@Overridepublic void run(ApplicationArguments args) throws Exception {// 存储字符串对象redisTemplate.opsForValue().set("name", "张三");String str = (String) redisTemplate.opsForValue().get("name");System.out.println(str);// 存储实体类型redisTemplate.opsForValue().set("user:1", new User(1L, "张三"));User user = (User) redisTemplate.opsForValue().get("user:1");System.out.println(user);}}
127.0.0.1:6379> keys *1) "user:1"2) "name"127.0.0.1:6379> get name"\"\xe5\xbc\xa0\xe4\xb8\x89\""127.0.0.1:6379> get user:1"{\"@class\":\"org.masteryourself.tutorial.spring.data.redis.entity.User\",\"id\":1,\"name\":\"\xe5\xbc\xa0\xe4\xb8\x89\"}"
3.2.3 StringRedisTemplate
Spring 默认提供了一个 StringRedisTemplate类,它的 key 和 value 的序列化方式默认就是 String 方式
@SpringBootApplicationpublic class SpringDataRedisApplication implements ApplicationRunner {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;public static void main(String[] args) {SpringApplication.run(SpringDataRedisApplication.class, args);}@Overridepublic void run(ApplicationArguments args) throws Exception {// 存储字符串对象stringRedisTemplate.opsForValue().set("name", "张三");String str = stringRedisTemplate.opsForValue().get("name");System.out.println(str);// 存储实体类型ObjectMapper mapper = new ObjectMapper();User userWrite = new User(1L, "张三");stringRedisTemplate.opsForValue().set("user:1", mapper.writeValueAsString(userWrite));String jsonStr = stringRedisTemplate.opsForValue().get("user:1");User readUser = mapper.readValue(jsonStr, User.class);System.out.println(readUser);}}
127.0.0.1:6379> keys *1) "user:1"2) "name"127.0.0.1:6379> get name"\xe5\xbc\xa0\xe4\xb8\x89"127.0.0.1:6379> get user:1"{\"id\":1,\"name\":\"\xe5\xbc\xa0\xe4\xb8\x89\"}"
