1. 安装 Redis

1.1 安装

  1. # Redis 是 c 语言编写,需要安装依赖库
  2. yum install -y gcc tcl
  3. # 上传压缩包后解压
  4. tar -xzf redis-6.2.6.tar.gz
  5. # 进入 Redis 目录
  6. cd redis-6.2.6
  7. # 编译安装
  8. make && make install

1.2 启动

1.2.1 指定配置文件启动

  1. # 允许访问的地址,默认是 127.0.0.1,会导致只能在本地访问。修改为 0.0.0.0 则可以在任意 IP 访问
  2. bind 0.0.0.0
  3. # 守护进程,修改为yes后即可后台运行
  4. daemonize yes
  5. # 密码,设置后访问 Redis 必须输入密码
  6. requirepass 123321
  7. # 监听的端口
  8. port 6379
  9. # 工作目录,默认是当前目录,也就是运行 redis-server 时的命令,日志、持久化等文件会保存在这个目录
  10. dir .
  11. # 数据库数量,设置为 1,代表只使用 1 个库,默认有 16 个库,编号 0~15
  12. databases 1
  13. # 设置 redis 能够使用的最大内存
  14. maxmemory 512mb
  15. # 日志文件,默认为空,不记录日志,可以指定日志文件名
  16. logfile "redis.log"
  1. # 启动
  2. redis-server redis.conf

1.2.2 开机自启

  1. # 新建一个系统服务文件,文件内容见下方
  2. vi /etc/systemd/system/redis.service
  3. # 重载系统服务
  4. systemctl daemon-reload
  1. [Unit]
  2. Description=redis-server
  3. After=network.target
  4. [Service]
  5. Type=forking
  6. ExecStart=/usr/local/bin/redis-server /usr/local/redis-6.2.6/redis.conf
  7. PrivateTmp=true
  8. [Install]
  9. WantedBy=multi-user.target
  1. # 启动
  2. systemctl start redis
  3. # 停止
  4. systemctl stop redis
  5. # 重启
  6. systemctl restart redis
  7. # 查看状态
  8. systemctl status redis

2. Redis 常见命令

2.1 通用命令

通用指令是部分数据类型的,都可以使用的指令,常见的有:

  1. KEYS:查看符合模板的所有 key
  2. DEL:删除一个指定的 key
  3. EXISTS:判断 key 是否存在
  4. EXPIRE:给一个 key 设置有效期,有效期到期时该 key 会被自动删除
  5. TTL:查看一个KEY的剩余有效期

2.2 String 类型

String 类型,也就是字符串类型,是 Redis 中最简单的存储类型。其 value 是字符串,不过根据字符串的格式不同,又可以分为3类:

  • string:普通字符串
  • int:整数类型,可以做自增、自减操作
  • float:浮点类型,可以做自增、自减操作

不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过 512m

  1. SET:添加或者修改已经存在的一个 String 类型的键值对
  2. GET:根据 key 获取 String 类型的 value
  3. MSET:批量添加多个String类型的键值对
  4. MGET:根据多个 key 获取多个 String 类型的 value
  5. INCR:让一个整型的 key 自增 1
  6. INCRBY:让一个整型的 key 自增并指定步长,例如:incrby num 2 num 值自增 2
  7. INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
  8. SETNX:添加一个 String 类型的键值对,前提是这个 key 不存在,否则不执行
  9. SETEX:添加一个 String 类型的键值对,并且指定有效期

2.3 Hash 类型

Hash 类型,也叫散列,其 value 是一个无序字典,类似于 Java 中的 HashMap 结构

String 结构是将对象序列化为 JSON 字符串后存储,当需要修改对象某个字段时很不方便

Hash 结构可以将对象中的每个字段独立存储,可以针对单个字段做 CRUD

  1. HSET key field value:添加或者修改 hash 类型 key field 的值
  2. HGET key field:获取一个 hash 类型 key field 的值
  3. HMSET:批量添加多个 hash 类型 key field 的值
  4. HMGET:批量获取多个 hash 类型 key field 的值
  5. HGETALL:获取一个 hash 类型的 key 中的所有的 field value
  6. HKEYS:获取一个 hash 类型的 key 中的所有的 field
  7. HVALS:获取一个 hash 类型的 key 中的所有的 value
  8. HINCRBY:让一个 hash 类型 key 的字段值自增并指定步长
  9. HSETNX:添加一个 hash 类型的 key field 值,前提是这个 field 不存在,否则不执

2.4 List 类型

Redis 中的 List 类型与 Java 中的 LinkedList 类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索,特征也与 LinkedList 类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般

常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等

  1. LPUSH key element ... :向列表左侧插入一个或多个元素
  2. LPOP key:移除并返回列表左侧的第一个元素,没有则返回 nil
  3. RPUSH key element ... :向列表右侧插入一个或多个元素
  4. RPOP key:移除并返回列表右侧的第一个元素
  5. LRANGE key star end:返回一段角标范围内的所有元素
  6. BLPOP BRPOP:与 LPOP RPOP 类似,只不过在没有元素时等待指定时间,而不是直接返回 nil

如何利用 List 结构模拟一个栈

  • 入口和出口在同一边

如何利用 List 结构模拟一个队列

  • 入口和出口在不同边

如何利用 List 结构模拟一个阻塞队列

  • 入口和出口在不同边出队时
  • 采用 BLPOP 或 BRPOP

    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 的并集

  1. <a name="WukA4"></a>
  2. ## 2.6 SortedSet 类型
  3. Redis 的 SortedSet 是一个可排序的set集合,与 Java 中的 TreeSet 有些类似,但底层数据结构却差别很大。SortedSet 中的每一个元素都带有一个 score 属性,可以基于 score 属性对元素排序,底层的实现是一个跳表(SkipList)+ hash 表。
  4. SortedSet 具备下列特性:
  5. - 可排序
  6. - 元素不重复
  7. - 查询速度快
  8. - 因为 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 即可

  1. <a name="yA3zb"></a>
  2. # 3. SpringDataRedis
  3. <a name="P48mM"></a>
  4. ## 3.1 介绍
  5. SpringData 是 Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 的集成模块就叫做 SpringDataRedis,官网地址是[https://spring.io/projects/spring-data-redis](https://spring.io/projects/spring-data-redis)
  6. - 提供了对不同 Redis 客户端的整合(Lettuce 和 Jedis)
  7. - 提供了 RedisTemplate 统一 API 来操作 Redis
  8. - 支持 Redis 的发布订阅模型
  9. - 支持 Redis 哨兵和 Redis 集群
  10. - 支持基于 Lettuce 的响应式编程
  11. - 支持基于 JDK、JSON、字符串、Spring 对象的数据序列化及反序列化
  12. - 支持基于 Redis 的 JDKCollection 实现
  13. SpringDataRedis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作。并且将不同数据类型的操作 API 封装到了不同的类型中
  14. | API | 返回值类型 | 说明 |
  15. | --- | --- | --- |
  16. | **redisTemplate**.opsForValue() | ValueOperations | 操作 String 类型数据 |
  17. | **redisTemplate**.opsForHash() | HashOperations | 操作 Hash 类型数据 |
  18. | **redisTemplate**.opsForList() | ListOperations | 操作 List 类型数据 |
  19. | **redisTemplate**.opsForSet() | SetOperations | 操作 Set 类型数据 |
  20. | **redisTemplate**.opsForZSet() | ZSetOperations | 操作 SortedSet 类型数据 |
  21. | **redisTemplate** | | 通用的命令 |
  22. <a name="XylVM"></a>
  23. ## 3.2 序列化方式
  24. <a name="oWmgF"></a>
  25. ### 3.2.1 JDK 序列化方式
  26. 因为默认使用的 `JdkSerializationRedisSerializer`序列化方式,所以这里的 key 和 value 都变成了如下格式
  27. ```java
  28. @Data
  29. @NoArgsConstructor
  30. @AllArgsConstructor
  31. public class User implements Serializable {
  32. private Long id;
  33. private String name;
  34. }
  1. @SpringBootApplication
  2. public class SpringDataRedisApplication implements ApplicationRunner {
  3. @Autowired
  4. private RedisTemplate redisTemplate;
  5. public static void main(String[] args) {
  6. SpringApplication.run(SpringDataRedisApplication.class, args);
  7. }
  8. @Override
  9. public void run(ApplicationArguments args) throws Exception {
  10. // 存储字符串对象
  11. redisTemplate.opsForValue().set("name", "张三");
  12. System.out.println(redisTemplate.opsForValue().get("name"));
  13. // 存储实体类型
  14. redisTemplate.opsForValue().set("user:1", new User(1L, "张三"));
  15. System.out.println(redisTemplate.opsForValue().get("user:1"));
  16. }
  17. }
  1. 127.0.0.1:6379> keys *
  2. 1) "\xac\xed\x00\x05t\x00\x06user:1"
  3. 2) "\xac\xed\x00\x05t\x00\x04name"
  4. 127.0.0.1:6379> get \xac\xed\x00\x05t\x00\x04name
  5. (nil)
  6. 127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x04name"
  7. "\xac\xed\x00\x05t\x00\x06\xe5\xbc\xa0\xe4\xb8\x89"
  8. 127.0.0.1:6379> get "\xac\xed\x00\x05t\x00\x06user:1"
  9. "\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,会带来额外的内存开销

  1. @Configuration
  2. public class RedisConfig {
  3. @Bean
  4. public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  5. // 创建Template
  6. RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  7. // 设置连接工厂
  8. redisTemplate.setConnectionFactory(redisConnectionFactory);
  9. // 设置序列化工具
  10. GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  11. // key 和 hashKey 采用 string 序列化
  12. redisTemplate.setKeySerializer(RedisSerializer.string());
  13. redisTemplate.setHashKeySerializer(RedisSerializer.string());
  14. // value 和 hashValue采用 JSON 序列化
  15. redisTemplate.setValueSerializer(jsonRedisSerializer);
  16. redisTemplate.setHashValueSerializer(jsonRedisSerializer);
  17. return redisTemplate;
  18. }
  19. }
  1. @SpringBootApplication
  2. public class SpringDataRedisApplication implements ApplicationRunner {
  3. @Autowired
  4. private RedisTemplate<String, Object> redisTemplate;
  5. public static void main(String[] args) {
  6. SpringApplication.run(SpringDataRedisApplication.class, args);
  7. }
  8. @Override
  9. public void run(ApplicationArguments args) throws Exception {
  10. // 存储字符串对象
  11. redisTemplate.opsForValue().set("name", "张三");
  12. String str = (String) redisTemplate.opsForValue().get("name");
  13. System.out.println(str);
  14. // 存储实体类型
  15. redisTemplate.opsForValue().set("user:1", new User(1L, "张三"));
  16. User user = (User) redisTemplate.opsForValue().get("user:1");
  17. System.out.println(user);
  18. }
  19. }
  1. 127.0.0.1:6379> keys *
  2. 1) "user:1"
  3. 2) "name"
  4. 127.0.0.1:6379> get name
  5. "\"\xe5\xbc\xa0\xe4\xb8\x89\""
  6. 127.0.0.1:6379> get user:1
  7. "{\"@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 方式

  1. @SpringBootApplication
  2. public class SpringDataRedisApplication implements ApplicationRunner {
  3. @Autowired
  4. private RedisTemplate<String, Object> redisTemplate;
  5. @Autowired
  6. private StringRedisTemplate stringRedisTemplate;
  7. public static void main(String[] args) {
  8. SpringApplication.run(SpringDataRedisApplication.class, args);
  9. }
  10. @Override
  11. public void run(ApplicationArguments args) throws Exception {
  12. // 存储字符串对象
  13. stringRedisTemplate.opsForValue().set("name", "张三");
  14. String str = stringRedisTemplate.opsForValue().get("name");
  15. System.out.println(str);
  16. // 存储实体类型
  17. ObjectMapper mapper = new ObjectMapper();
  18. User userWrite = new User(1L, "张三");
  19. stringRedisTemplate.opsForValue().set("user:1", mapper.writeValueAsString(userWrite));
  20. String jsonStr = stringRedisTemplate.opsForValue().get("user:1");
  21. User readUser = mapper.readValue(jsonStr, User.class);
  22. System.out.println(readUser);
  23. }
  24. }
  1. 127.0.0.1:6379> keys *
  2. 1) "user:1"
  3. 2) "name"
  4. 127.0.0.1:6379> get name
  5. "\xe5\xbc\xa0\xe4\xb8\x89"
  6. 127.0.0.1:6379> get user:1
  7. "{\"id\":1,\"name\":\"\xe5\xbc\xa0\xe4\xb8\x89\"}"