Redis-Day1基础篇
- 初识Redis
- 认识NoSQL
- 认识Redis
- 安装Redis
- 启动Redis
- Redis客户端
- Redis命令
- 数据结构介绍
- 通用命令
- 操作命令
- String
- Hash
- List
- Set
- SortedSet
- Redis的Java客户端
- 客户端对比
- Jedis客户端
- Jedis快速入门
- Jedis连接池
- SpringDataRedis客户端
- SpringDataRedis概述
- SpringDataRedis快速入门
- RedisTemplate的RedisSerializer
- StringRedisTemplate
- RedisTemplate操作Hash类型
- 来源
- Gitee地址
初识Redis
认识NoSQL
认识Redis
- 键值(key-value)型, value支持多种不同数据结构, 功能丰富
- 单线程, 每个命令具备原子性
- 低延迟, 速度快(基于内存, io多路复用, 良好的编码)
- 支持数据持久化
- 支持主从集群, 分片集群
- 支持多语言客户端
安装Redis
- 安装Redis依赖
yum install -y gcc tcl
- 上传安装包并解压
将压缩包放到/usr/local/src目录下
默认的安装路径在/usr/local/bin目录下, 该目录默认配置环境变量# 解压缩 tar -zxvf redis-6.2.6.tar.gz # 进入redis目录 cd redis-6.2.6 # 运行编译命令 make && make install
redis-cli:是redis提供的命令行客户端 redis-server:是redis的服务端启动脚本 redis-sentinel:是redis的哨兵启动脚本
启动Redis
- 默认启动(前台启动)
redis-server
- 指定配置启动(后台启动)
修改配置文件# 进入redis安装包目录 cd /usr/local/src/redis-6.2.6 # 备份配置文件 cp redis.conf redis.conf.bck
启动Redis# 监听的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0 bind 0.0.0.0 # 守护进程,修改为yes后即可后台运行 daemonize yes # 密码,设置后访问Redis必须输入密码 requirepass 123456 # 监听的端口 port 6379 # 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录 dir . # 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15 databases 1 # 没改 # 设置redis能够使用的最大内存 maxmemory 512mb # 没改 # 日志文件,默认为空,不记录日志,可以指定日志文件名 logfile "redis.log"
# 进入redis安装目录 cd /usr/local/src/redis-6.2.6 # 启动 redis-server redis.conf
- 开机自启
首先, 新建一个配置文件
内容如下vi /etc/systemd/system/redis.service
然后重载系统服务[Unit] Description=redis-server After=network.target [Service] Type=forking ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf PrivateTmp=true [Install] WantedBy=multi-user.target
现在,我们可以用下面这组命令来操作redis了systemctl daemon-reload
执行下面的命令,可以让redis开机自启# 启动 systemctl start redis # 停止 systemctl stop redis # 重启 systemctl restart redis # 查看状态 systemctl status redis
systemctl enable redis
Redis客户端
-
命令行客户端
redis-cli [options] [commonds]
常见的options有
-h 127.0.0.1
: 指定要连接的redis节点的ip地址, 默认127.0.0.1-p 6379
: 指定要连接的redis节点的端口, 默认6379-a 123456
: 指定redis的访问密码- 安全的密码验证方式: 启动
redis-cli
后输入AUTH 123456
commonds是redis的操作命令
ping
: 与redis服务端做心跳测试, 服务端支持会返回pong
- 不知道commond时, 进入
redis-cli
的交互控制台
选择库
select 0
-
图形化客户端
安装包: https://github.com/lework/RedisDesktopManager-Windows/releases
Redis命令
数据结构介绍
通用命令
keys
: 查看符合模板的所有key, 不建议在生产环境设备上使用del
: 删除一个指定的keyexists
: 判断key是否存在expire
: 给一个key设置有效期, 有效期到期时该key会被自动删除ttl
: 查看一个key的剩余有效期(-2表示不存在, -1表示永久)
操作命令
String
value是字符串类型, 底层都是字节数组形式存储, 分为3类:
string
: 普通字符串int
: 整数类型, 可以自增减float
: 浮点类型, 可以自增减
常见命令
SET
: 添加或者修改已经存在的一个string类型的键值对GET
: 根据key获取String类型的valueMSET
: 批量添加多个String类型的键值对MGET
: 根据多个key获取多个String类型的valueINCR
: 让一个整型的key自增1INCRBY
: 让一个整型的key自增并指定步长,例如:incrby num 2
让num值自增2INCRBYFLOAT
: 让一个浮点类型的数字自增并指定步长SETNX
: 添加一个String类型的键值对,前提是这个key不存在,否则不执行SETEX
: 添加一个string类型的键值对,并且指定有效期
Redis的key的格式(建议)
[项目名]:[业务名]:[类型]:[id]
Hash
Hash类型, value是一个无序字典, 与java的HashMap类似
- 场景: string结构是将对象序列化为JSON字符串后存储, 修改某个字段不方便
常见命令
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不存在,否则不执行
List
与java的LinkedList类似, 可以看作是双向链表结构. 支持双向检索
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用语法
LPUSH key element ...
: 向列表左侧插入一个或多个元素LPOP key
: 移除并返回列表左侧的第一个元素,没有则返回nilRPUSH key element ...
: 向列表右侧插入一个或多个元素RPOP key
: 移除并返回列表右侧的第一个元素LRANGE key starend
: 返回一段角标范围内的所有元素BLPOP和BRPOP
: 与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
Set
与java的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的并集
SortedSet
是一个可排序的set集合, 与java中的TreeSet有些类似, 但底层数据结构差别很大.SortedSet中的每一个元素都带有一个score属性, 基于score属性对元素排序, 底层是一个跳表(SkipList)加Hash表.
- 可排序
- 元素不重复
- 查询速度快
可用来实现排行榜的功能
常见命令
ZADD key score member
: 添加一个或多个元素到sorted set,如果已经存在则更新其score值ZREM key member
: 删除sorted set中的一个指定元素ZSCORE key member
: 获取srted 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
: 按照sore排序后,获取指定score范围内的元素ZDIFF、ZINTER、ZUNION
: 求差集、交集、并集- 注意: 默认升序, 降序需要在命令的
Z
后面添加REV
:ZREVRANK
Redis的Java客户端
客户端对比
Spring Data Redis 整合了 Jedis 和 lettuce
Jedis客户端
Jedis快速入门
- 引入依赖
<!-- Jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> <scope>test</scope> </dependency>
- 使用
import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import redis.clients.jedis.Jedis; import java.util.Map; @Slf4j public class JedisTest { private Jedis jedis; // 1. 建立连接 @BeforeEach void setUp(){ // 建立连接 jedis = new Jedis("192.168.174.133", 6379); // 密码验证 jedis.auth("123456"); // 选择库, 默认0 jedis.select(0); } // 4. 释放资源 @AfterEach void tearDown(){ // 释放资源 if(jedis != null){ jedis.close(); } } // 2. 测试String @Test void testString(){ // 插入数据, 方法名就是redis命令名 String res = jedis.set("name", "zhangsan"); System.out.println("result = " + res); // 获取数据 String name = jedis.get("name"); System.out.println("name = " + name); } // 3. 测试Hash @Test void testHash() { // 插入数据 jedis.hset("user:1", "name", "tom"); jedis.hset("user:1", "age", "20"); // 获取数据 Map<String, String> map = jedis.hgetAll("user:1"); System.out.println(map); } }
Jedis连接池
- 工具类
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class JedisConnectionFactory { private static final JedisPool jedisPool; static { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); // 最大连接 jedisPoolConfig.setMaxTotal(8); // 最大空闲连接 jedisPoolConfig.setMaxIdle(8); // 最小空闲连接 jedisPoolConfig.setMinIdle(0); // 设置最长等待时间, ms jedisPoolConfig.setMaxWaitMillis(200); jedisPool = new JedisPool(jedisPoolConfig, "192.168.174.133", 6379, 1000, "123456"); } public static Jedis getJedis(){ return jedisPool.getResource(); } }
- 使用
... public class JedisTest { private Jedis jedis; // 建立连接 @BeforeEach void setUp(){ // 建立连接 // jedis = new Jedis("192.168.174.133", 6379); jedis = JedisConnectionFactory.getJedis(); ... } ... }
SpringDataRedis客户端
SpringDataRedis概述
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis
官网地址: https://spring.io/projects/spring-data-redis
- 提供了对不同Redis客户端的整合 (Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
SpringDataRedis提供了RedisTemplate工具类
SpringDataRedis快速入门
- 引入依赖
<!-- Redis依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 连接池依赖 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
- 配置文件
spring: data: redis: host: 192.168.174.133 port: 6379 password: 123456 lettuce: pool: max-active: 8 # 最大连接 max-idle: 8 # 最大空闲连接 min-idle: 0 # 最小空闲连接 max-wait: 100 # 设置最长等待时间, ms
- 使用
@SpringBootTest class SpringdataredisDemoApplicationTests { @Autowired private RedisTemplate redisTemplate; @Test void testString() { // 插入一条string类型数据 redisTemplate.opsForValue().set("name", "李四"); // 读取一条string类型数据 Object name = redisTemplate.opsForValue().get("name"); System.out.println("name = " + name); } }
RedisTemplate的RedisSerializer
RedisTemplate可以接收任意Object作为值写入Redis, 但是写入前会把Object序列化为字节形式, 默认是采用JDK序列化
- 可读性差
- 内存占用较大
使用JSON序列化, 配置类如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
// 创建RedisTemplate对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
// 返回
return redisTemplate;
}
}
StringRedisTemplate
- JSON序列化器会将类的class类型写入json结果中, 插入redis, 会带来额外的内存开销
- 统一使用String序列化器, 要求只能存储String类型的key和value, 需要存储对象时, 手动完成对象的序列化和反序列化
- Spring默认提供了StringRedisTemplate类
@SpringBootTest class StringRedisTemplateTests { @Autowired private StringRedisTemplate stringRedisTemplate; // SpringMVC框架默认使用的JSON处理工具 private static final ObjectMapper mapper = new ObjectMapper(); @Test void testSaveUser() throws JsonProcessingException { // 创建对象 User user = new User("jerry", 21); // 手动序列化 String json = mapper.writeValueAsString(user); // 写入数据 stringRedisTemplate.opsForValue().set("user:2", json); // 获取数据 String jsonUser = stringRedisTemplate.opsForValue().get("user:2"); // 手动反序列化 User user1 = mapper.readValue(jsonUser, User.class); System.out.println("user1 = " + user1); } }
RedisTemplate操作Hash类型
...
@SpringBootTest
class StringRedisTemplateTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
...
@Test
void testHash() {
stringRedisTemplate.opsForHash().put("user:3", "name", "tom");
stringRedisTemplate.opsForHash().put("user:3", "age", "21");
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:3");
System.out.println(entries);
}
}
来源
黑马程序员. Redis入门到实战教程
Gitee地址
https://gitee.com/Y_cen/redis