一、redis部署
1、关闭防火墙
关闭防火墙:
systemctl stop firewalld.service
状态:
firewall-cmd --state
卸载防火墙
yum remove firewalld
2、CentOS7部署redis
1、检查编译运行环境,是否有 GCC 编译器
检查环境(gcc):
gcc --version
安装gcc:
yum install gcc
2、安装redis
创建文件夹:
mkdir -p /opt/software/redis
cd /opt/software/redis
下载redis:
wget https://download.redis.io/redis-stable.tar.gz
解压:
tar -zxf redis-stable.tar.gz
安装:
cd redis-stable
make install
3、启动服务(静默启动)
修改redis.conf配置文件:
vim redis.conf
//修改可以登录的ip及端口
bind * -::*
bind 0.0.0.0 (外网)
//允许后台启动
daemonize yes
//配置日志文件
logfile /opt/software/redis/redis-stable/redis.log
//指定工作目录
dir /opt/software/redis
//设置密码
requirepass Zxc61415
//保护模式(打开只允许本地连接)
protected-mode yes
//持久话
appendonly yes
//启动
redis-server redis.conf
//关闭
redis-cli -a Zxc61415 shutdown
3、docker部署redis
1、拉取镜像
docker pull redis:7.0.10
2、在宿主机的 /var/lib/docker/volumes/redis-config/_data/目录下创建一个redis的配置文件
如果/var/lib/docker/volumes没有redis-config,创建数据卷
docker volume create redis-config
vim redis.conf
# 内容如下所示
#开启持久化
appendonly yes
port 6379
# requirepass 1234
bind 0.0.0.0
3、创建容器
docker run -d -p 6379:6379 --restart=always \
-v redis-config:/etc/redis/config \
-v redis-data:/data \
--name redis redis:7.0.10 \
redis-server /etc/redis/config/redis.conf
二、redis的基本数据类型、操作和使用场景
1、redis基本操作
|-------------|---------------------------------------------|
| set 设置 | set name zxc |
| 查看所有的key | keys * |
| get 获取 | get name |
| 叠加/减计 | incr num decr num incrby num 5 decrby num 5 |
| setnx 设置不存在 | setnx lock1 1 |
| del 删除 | del lock1 |
| 清空所有数据 | flushdb |
2、string类型
使用场景:
- 存储Session
- 实现验证码
- 实现计数器
- 实现锁
Java代码:
java
@SpringBootTest
public class RedisTemplateTestJsonTest {
@Autowired
private RedisTemplate redisTemplate;
//缓存
@Test
public void test(){
redisTemplate.opsForValue().set("k1","999",30, TimeUnit.SECONDS);
Object object = redisTemplate.opsForValue().get("k1");
System.out.println("object = " + object);
}
//计数
@Test
public void test01(){
redisTemplate.opsForValue().set("num",1);
Object object = redisTemplate.opsForValue().get("num");
Long num = redisTemplate.opsForValue().increment("num"); //+1
System.out.println("num = " + num);
Long num1 = redisTemplate.opsForValue().decrement("num"); //-1
System.out.println("num1 = " + num1);
}
//setnx锁
@Test
public void lockTest(){
redisTemplate.opsForValue().setIfAbsent("lock1",1);
Boolean lock1 = redisTemplate.opsForValue().setIfAbsent("lock1", 1,30,TimeUnit.SECONDS);
System.out.println("lock1 = " + lock1);
}
}
2、list类型
使用场景:
- 排序
- 最新
- 自定义栈
- 自定义队列
基本操作:
|-------------------|---------------------|
| 头插 | lpush message 1 2 3 |
| 获取(范围 -1表示所有) | lrange message 0 -1 |
| 头取(取出数据并删除) | lpop message |
| 尾插 | rpush queue 1 2 3 |
| 尾取(取出数据并删除) | rpop queue |
| 获取数组长度 | llen queue |
| 获取下标元素(从0开始,不会删除) | lindex queue 2 |
[list基本操作]
Java代码:
java
@SpringBootTest
public class OpsForListTest {
@Autowired
private RedisTemplate redisTemplate;
//数组
@Test
public void listtest(){
redisTemplate.opsForList().leftPush("list",1);
redisTemplate.opsForList().leftPush("list",2);
redisTemplate.opsForList().leftPush("list",3);
List list = redisTemplate.opsForList().range("list", 0, -1);
System.out.println(redisTemplate.opsForList().size("list"));
list.forEach(num -> System.out.println("num = " + num));
}
//栈
@Test
public void stacktest(){
redisTemplate.opsForList().leftPush("stack",1);
redisTemplate.opsForList().leftPush("stack",2);
redisTemplate.opsForList().leftPush("stack",3);
List list = new ArrayList<>();
list.add(redisTemplate.opsForList().leftPop("stack"));
list.add(redisTemplate.opsForList().leftPop("stack"));
list.add(redisTemplate.opsForList().leftPop("stack"));
list.forEach(num -> System.out.print(num + " , "));
}
//队列
@Test
public void queuetest(){
redisTemplate.opsForList().leftPush("queue",1);
redisTemplate.opsForList().leftPush("queue",2);
redisTemplate.opsForList().leftPush("queue",3);
List list = new ArrayList<>();
list.add(redisTemplate.opsForList().rightPop("queue"));
list.add(redisTemplate.opsForList().rightPop("queue"));
list.add(redisTemplate.opsForList().rightPop("queue"));
list.forEach(num -> System.out.print(num + " , "));
}
}
3、hash类型
使用场景:
- 存储对象
- 购物车
基本操作:
|--------|-----------------------------------------------------|
| 设置 | hset user:001 name zxc age 20 |
| 设置多个值 | hmset user:002 name qh age 23 |
| 获取所有属性 | hgetall user:001 |
| 获取单个值 | hget user:001 name |
| 修改单个值 | hset user:001 name zxx |
| 获取长度 | hlen cart:001 |
| 删除 | hdel cart:001 1 |
| 数据加/减 | hincrby cart:001 10086 10 hincrby cart:001 10086 -5 |
Java代码:
java
@SpringBootTest
public class OpsForHash {
@Autowired
private RedisTemplate redisTemplate;
//存储对象
@Test
public void test(){
redisTemplate.opsForHash().put("user:01","name","zxc");
redisTemplate.opsForHash().put("user:01","age",12);
System.out.println(redisTemplate.opsForHash().get("user:01", "name"));
System.out.println(redisTemplate.opsForHash().get("user:01", "age"));
Map map = new HashMap<>();
map.put("name","qh");
map.put("age",23);
redisTemplate.opsForHash().putAll("user:02",map);
System.out.println(redisTemplate.opsForHash().get("user:02", "name"));
System.out.println(redisTemplate.opsForHash().get("user:02", "age"));
}
//购物车
@Test
public void carttest(){
redisTemplate.opsForHash().put("cart:01","goods:01",4);
redisTemplate.opsForHash().put("cart:01","goods:02",5);
System.out.println(redisTemplate.opsForHash().size("cart:01"));
redisTemplate.opsForHash().increment("cart:01","goods:01",5);
redisTemplate.opsForHash().increment("cart:01","goods:01",-2);
Map entries = redisTemplate.opsForHash().entries("cart:01");
Set set = entries.entrySet();
entries.keySet().forEach(key-> System.out.println(key));
set.forEach(entry-> System.out.println(entry));
}
}
4、set类型
使用场景:
- 随机(抽奖)
- 点赞
基本操作:
|-------------|-------------------|
| 添加 | sadd luck1 1 2 3 |
| 查看 | smembers luck1 |
| 随机取出一个(并删除) | spop luck1 |
| 删除一个值 | srem luck1 1 |
| 统计数量 | scard luck1 |
| 查找是否存在 | sismember luck1 1 |
Java代码:
java
@SpringBootTest
public class OpsForSet {
@Resource
private RedisTemplate redisTemplate;
@Test
public void test(){
redisTemplate.opsForSet().add("luck",1);
redisTemplate.opsForSet().add("luck",2);
redisTemplate.opsForSet().add("luck",3);
System.out.println(redisTemplate.opsForSet().members("luck"));
System.out.println(redisTemplate.opsForSet().size("luck"));
}
//抽奖
@Test
public void randomTest(){
redisTemplate.opsForSet().add("person","qh","zxc","hz");
System.out.println(redisTemplate.opsForSet().randomMember("person"));
//或者(删除)
System.out.println(redisTemplate.opsForSet().pop("person"));
System.out.println(redisTemplate.opsForSet().members("person"));
}
//点赞
@Test
public void add(){
redisTemplate.opsForSet().add("like","qh","zxc","hz");
System.out.println(redisTemplate.opsForSet().members("like"));
redisTemplate.opsForSet().add("like","yx");
System.out.println(redisTemplate.opsForSet().members("like"));
redisTemplate.opsForSet().remove("like","yx");
System.out.println(redisTemplate.opsForSet().members("like"));
}
}
5、zset类型
使用场景:
- 排行榜(排序)
基本操作:
|-----------------|---------------------------------|
| 添加 | zadd sort 1 qh zadd sort 2 zxc |
| 查看(范围-分数) | zrevrange sort 0 -1 withscores |
| 添加 | zincrby sort 2 zxc |
| 合并set(同key分数累加) | zunionstore newset 2 sort sort1 |
Java代码:
java
@SpringBootTest
public class OpsForZSet {
@Resource
private RedisTemplate redisTemplate;
//排行榜
@Test
public void sort(){
redisTemplate.opsForZSet().add("sort1","zxc",1);
redisTemplate.opsForZSet().add("sort1","qh",2);
redisTemplate.opsForZSet().add("sort1","hz",3);
System.out.println(redisTemplate.opsForZSet().reverseRange("sort1", 0, -1));
redisTemplate.opsForZSet().incrementScore("sort1","qh",2);
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort1", 0, -1));
redisTemplate.opsForZSet().add("sort2","zxc",5);
redisTemplate.opsForZSet().add("sort2","qh",2);
redisTemplate.opsForZSet().add("sort2","hz",3);
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort2", 0, -1));
redisTemplate.opsForZSet().unionAndStore("sort1","sort2","sort");
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort", 0, -1));
}
//合并多个
@Test
public void sort2(){
redisTemplate.opsForZSet().add("sort1","zxc",1);
redisTemplate.opsForZSet().add("sort1","qh",2);
redisTemplate.opsForZSet().add("sort1","hz",3);
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort1", 0, -1));
redisTemplate.opsForZSet().add("sort2","zxc",5);
redisTemplate.opsForZSet().add("sort2","qh",3);
redisTemplate.opsForZSet().add("sort2","hz",1);
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort2", 0, -1));
redisTemplate.opsForZSet().add("sort3","zxc",2);
redisTemplate.opsForZSet().add("sort3","qh",2);
redisTemplate.opsForZSet().add("sort3","hz",2);
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort3", 0, -1));
List<String> list = new ArrayList<>();
list.add("sort2");
list.add("sort3");
redisTemplate.opsForZSet().unionAndStore("sort1",list,"sort");
System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("sort", 0, -1));
}
}
三、持久化
1、RDB
RDB进行持久化是将当前进程的数据生成快照保存到硬盘中的过程
优点是:占用的空间少、恢复快;
缺点是:由于数据是定时保存,所以在下次保存前服务关闭会导致数据丢失。
2、AOF
AOF是Append Only File,是Redis中实现持久化的一种方式。以独⽴⽇志的⽅式记录每次命令,重启时再重新执⾏ AOF ⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是 Redis 持久化的主流⽅式。
开启AOF需要在 redis.conf 配置文件中将 appendonly 设置为 yes
优点是:不会造成数据丢失,或者只会丢失很少的数据;
缺点是:文件较大,由于恢复是重新构建数据,所以恢复的速度较慢。
四、redis的发布订阅模式
1、监听(一个消息会被多个监听)
java
subscribe name
2、发送
java
publish name message
五、springboot整合redis
1、导入依赖
java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
2、配置
java
spring:
data:
redis:
host: localhost
password: 123456
port: 6379
timeout: 60s
database: 0
3、序列化
java
public class DefaultSerializer implements RedisSerializer<Object> {
private final Charset charset;
public DefaultSerializer() {
this(Charset.forName("UTF8"));
}
public DefaultSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}
@Override
public byte[] serialize(Object o) throws SerializationException {
return o == null ? null : String.valueOf(o).getBytes(charset);
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
return bytes == null ? null : new String(bytes, charset);
}
}
java
@Configuration
public class AutoConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, String> redis = new RedisTemplate<>();
redis.setConnectionFactory(redisConnectionFactory);
// 设置redis的String/Value的默认序列化方式
DefaultSerializer stringRedisSerializer = new DefaultSerializer();
redis.setKeySerializer(stringRedisSerializer);
redis.setValueSerializer(stringRedisSerializer);
redis.setHashKeySerializer(stringRedisSerializer);
redis.setHashValueSerializer(stringRedisSerializer);
redis.afterPropertiesSet();
return redis;
}
}
4、使用
java
@SpringBootTest
public class RedisTemplateTestJsonTest {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
public void test(){
redisTemplate.opsForValue().set("k1","999",30, TimeUnit.SECONDS);
String s = redisTemplate.opsForValue().get("k1");
System.out.println("s = " + s);
}
}