Redis数据库✧完结篇

Redis✧数据库



一、Java集成Redis

✧ 方式一:通过Jedis作为java客户端对服务器进行连接
✧ 方式二:通过spring data redis作为客户端进行服务器连接


1、Jedis–Java版客户端

① 入门(依赖✧测试)
  • 直接引入依赖
 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
  </parent>

<dependencies>

    <!-- spring data redis 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <!--
          1.x 的版本默认采用的连接池技术是 Jedis,
          2.0 以上版本默认连接池是 Lettuce,
          如果采用 Jedis,需要排除 Lettuce 的依赖。
       -->
      <exclusions>
        <exclusion>
          <groupId>io.lettuce</groupId>
          <artifactId>lettuce-core</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <!-- jedis 依赖 -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
    </dependency>
    <!-- web 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- test 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

  </dependencies>

  • 创建测试类,直接测试向Linuxredis服务器发送请求
public class SpringTest {

    @Test
    public void test1(){
        Jedis jedis=new Jedis("192.168.168.129",6399);
        jedis.auth("123456");
        System.out.println(jedis.ping());
    }
}
//关闭防火墙:
//systemctl status firewalld 查看状态
//systemctl stop firewalld 关闭

记得启动Linux中的redis服务器,并且关闭Linux的防火墙
在这里插入图片描述
在这里插入图片描述


② 常用方式⭐
(1)配置redis–Application.yml
spring:
  redis:
    # Redis服务器地址
    host: 192.168.168.129
    # Redis服务器端口
    port: 6399
    # Redis服务器密码
    password: 123456
    # 选择哪个库,默认0库
    database: 0
    # 连接超时时间
    timeout: 10000ms
    jedis:
      pool:
        # 最大连接数,默认8
        max-active: 1024
        # 最大连接阻塞等待时间,单位毫秒,默认-1ms
        max-wait: 10000ms
        # 最大空闲连接,默认8
        max-idle: 200
        # 最小空闲连接,默认0
        min-idle: 5


(2)编写Redis配置类Redisconfig.java
  • 主要是为了方便获取资源配置一个RedisPool
@Configuration
public class Redisconfig {
    //服务器地址
    @Value("${spring.redis.host}")
    private String host;
    //端口
    @Value("${spring.redis.port}")
    private int port;
    //密码
    @Value("${spring.redis.password}")
    private String password;
    //超时时间
    @Value("${spring.redis.timeout}")
    private String timeout;
    //最大连接数
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxTotal;
    //最大连接阻塞等待时间
    @Value("${spring.redis.jedis.pool.max-wait}")
    private String maxWaitMillis;
    //最大空闲连接
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    //最小空闲连接
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
    @Bean
    public JedisPool redisPoolFactory(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //注意值的转变
        jedisPoolConfig.setMaxWaitMillis(Long.parseLong(maxWaitMillis.substring( 0,maxWaitMillis.length()-2)));
        //注意属性名
        jedisPoolConfig.setMaxTotal(maxTotal);
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(timeout.substring(0, timeout.length() - 2)), password);
        return jedisPool;
    }
}

(3)编写启动类和测试类
  • 启动类:
@SpringBootApplication
public class Start {
    public static void main(String[] args) {
        SpringApplication.run(Start.class,args);
    }
}
  • 测试类:
@SpringBootTest
public class RedisTest {

    @Resource//注入
    private JedisPool jedisPool;

    private Jedis jedis=null;


    @Test
    public void test01(){
        Jedis jedis=jedisPool.getResource();
        System.out.println(jedis.ping());
    }
}

注意此处的测试类与启动类的目录需要一致,否则需要加注解@SpringBootTest(classes = Start.class)指定启动类,否则报错
在这里插入图片描述


(4)测试常用数据结构:String,Hash,List
  • String 数据类型
@SpringBootTest
public class RedisTest {

    @Resource
    private JedisPool jedisPool;

    private Jedis jedis=null;

    @Test
    public void StringTest(){
        Jedis jedis=jedisPool.getResource();
        //添加
        System.out.println(jedis.set("添加", "添加成功"));
        //查询
        System.out.println(jedis.keys("*"));
        System.out.println(jedis.get("添加"));
        System.out.println(jedis.get("id"));
        //自增自减
        System.out.println(jedis.incr("id"));
        System.out.println(jedis.decr("id"));
        //定时
        jedis.setex("time",20,"开始计时");
        System.out.println(jedis.ttl("time"));
        jedis.expire("添加",100);
        //删除
        System.out.println(jedis.del("a"));
        jedis.close();
    }
}

在这里插入图片描述


  • Hash 数据类型
@SpringBootTest
public class RedisTest {

    @Resource
    private JedisPool jedisPool;

    private Jedis jedis=null;
    
    @Test
    public void HashTest(){
        Jedis jedis=jedisPool.getResource();
        Map<String,String> map=new HashMap<>();
        map.put("demo1","001");
        map.put("id","12");
        map.put("phone","1111");
        //添加
        System.out.println(jedis.hset("hash1", map));
        //查询
        System.out.println(jedis.hget("hash1", "id"));
        jedis.hgetAll("hash1").forEach((k,v)->{
            System.out.println("key"+"----"+k+"----"+"v"+"----"+v);
        });
        //自增
        System.out.println(jedis.hincrBy("hash1", "id", 10));
        System.out.println(jedis.hget("hash1", "id"));
        //位
        System.out.println(jedis.setbit("admin", 001, true));
        System.out.println(jedis.setbit("admin", 002, true));
        System.out.println(jedis.setbit("admin", 003, true));
        System.out.println(jedis.getbit("amdin", 003));
        //删除hdel是删除某个字段,del是删除键
        System.out.println(jedis.del("admin"));
        //hexists检查是否存在
        System.out.println(jedis.hexists("hash1", "id"));
        jedis.close();
    }
}

在这里插入图片描述


  • List 集合类型
    @Test
    public void ListTest() {
        Jedis jedis=jedisPool.getResource();
        System.out.println(jedis.lpush("list1", "aa", "bb", "cc"));
        System.out.println(jedis.rpush("list1", "dd"));
        System.out.println(jedis.lrange("list1",0,-1));
    }

在这里插入图片描述


2、Spring data redis–Java版客户端

① 入门(依赖✧测试)
  • 引入依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
</parent>
  
  <!--set、get等方法免写,注解@Data-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <!-- spring data redis 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- commons-pool2 对象池依赖 -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
    </dependency>
    <!-- web 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- test 组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

  • 创建测试类直接引入redisTemplate模板测试
@SpringBootTest(classes = Start.class)
public class LettuceTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test1(){
        redisTemplate.opsForValue().set("lettuce","demo");
        System.out.println(redisTemplate.opsForValue().get("lettuce"));
    }
}

通过客户端查看使用默认的模板,存入的数据进行了序列化,导致存入的是二进制内容
在这里插入图片描述
在这里插入图片描述

②常用方式⭐
(1)重写模板编写配置类RedisConfig.java
@Configuration
public class RedisConfig{
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<> ();
        //为string类型key设置序列器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //为string类型value设置序列器
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        //为hash类型key设置序列器
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //为hash类型value设置序列器
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}


(2)Application.yml 配置
spring:
  redis:
  # Redis服务器地址
    host: 192.168.168.129
  # Redis服务器端口
    port: 6399
  # Redis服务器端口
    password: 123456
  # Redis服务器端口
    database: 0
  # 连接超时时间
    timeout: 10000ms
    lettuce:
      pool:
      # 最大连接数,默认8
        max-active: 1024
      # 最大连接阻塞等待时间,单位毫秒,默认-1ms
        max-wait: 10000ms
        # 最大空闲连接,默认8
        max-idle: 200
        # 最小空闲连接,默认0
        min-idle: 5

(3)编写User类(测试使用)
@Data
public class User implements Serializable {
    private String name;
    private String phone;
}

(4)测试
@SpringBootTest(classes = Start.class)
public class LettuceTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test2(){
        redisTemplate.opsForValue().set("lettuce","demo");
        System.out.println(redisTemplate.opsForValue().get("lettuce"));
        User user=new User();
        user.setName("小王");
        user.setPhone("1012");
        redisTemplate.opsForValue().set("user",user);
        System.out.println(redisTemplate.opsForValue().get("user"));
    }
}

在这里插入图片描述
在这里插入图片描述


(5)常用数据结构测试

小细节:redis存储键值对形式 但String 和hash的区别在于:String存的格式:key:value hash存的格式:key:<key:value>


  • String 类型
@SpringBootTest
public class LettuceTest1 {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //valueOperations默认的需要redisTemplate作为参数,故在指定此注入
    @Resource(name = "redisTemplate")
    private ValueOperations<String,Object> valueOperations;//String的接口


    //String测试
    @Test
    public void test(){
        valueOperations.set("test001","test001");
        System.out.println(valueOperations.get("test001"));
        //批量增加
        Map<String,Object> map=new HashMap<>();
        map.put("demo1","100");
        map.put("demo2","200");
        valueOperations.multiSet(map);
        valueOperations.multiGet(map.keySet()).forEach(value->{
            System.out.println(value);
        });
        //自增
        System.out.println(valueOperations.increment("id", 10));
        //删除需要注入redisTemplate,因为接口valueOperations不提供删除
        System.out.println(redisTemplate.delete("demo1"));
        //设置过期时间TimeUnit.seconds时间单元
        valueOperations.set("demo2","200",300L, TimeUnit.SECONDS);
        //获取key的时间单元
        System.out.println(redisTemplate.getExpire("demo2"));
        //判断key
        System.out.println(redisTemplate.hasKey("demo1"));
        System.out.println(redisTemplate.type("demo2"));//STRING
    }

在这里插入图片描述

@Resource(name = "redisTemplate"):这里可能会误报错,不用管


  • Hash 类型
@SpringBootTest
public class LettuceTest1 {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //hash
    @Resource(name = "redisTemplate")
    private HashOperations<String,String,Object> hashOperations;

    //Hash
    @Test
    public void hash(){
        //添加
        Map<String,String> map=new HashMap<>();
        map.put("one","111");
        map.put("two","222");
        hashOperations.putAll("map1",map);
        //遍历
        hashOperations.multiGet("map1", Arrays.asList("one","two")).forEach(v->{
            System.out.println("value"+"----"+v);
        });
        //entries
        hashOperations.entries("map1").forEach((k,v)->{
            System.out.println("key"+"---"+k+"---"+"value"+"---"+v);
        });
        hashOperations.values("map1").forEach(v->{
            System.out.println("value"+"--"+v);
        });
        //自增
        hashOperations.put("map1","data",100);
        System.out.println(hashOperations.increment("map1", "data", 10));

    }
}

在这里插入图片描述


  • List 类型
@SpringBootTest
public class LettuceTest1 {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //list
    @Resource(name = "redisTemplate")
    private ListOperations<String,String> listOperations;

    //列表list
    @Test
    public void list(){
        System.out.println(listOperations.rightPushAll("java", "redis", "Spring", "SpringBoot"));
        System.out.println(listOperations.range("java", 0, -1));//[redis, Spring, SpringBoot]
        System.out.println(listOperations.index("java", 0));
        listOperations.set("java",2,"linux");
        System.out.println(listOperations.rightPop("java"));//linux
        System.out.println(listOperations.range("java", 0, -1));//[redis, Spring]
    }

}

在这里插入图片描述


二、读写分离✧主从复用⭐

在这里插入图片描述


1、读写分离
  • 读写分离:为什么要读写分离?当一台redis负责读又负责写时,数据量一旦大,效率会大大折扣,而读写分离主要就是通过读写功能的划分,提高效率。

① 在linux中配置公告配置文件

创建三个文件夹/opt/redis/data,log,conf

mkdir data log conf //批量创建文件夹

在这里插入图片描述


复制redis.conf至conf文件中命名为公共配置redis-common.conf

cp /user/redis/conf/redis.conf /opt/redis/conf/redis-common.conf

修改redis-common.conf内容⭐

①注释掉bind 127.0.0.1
②protected-mode:no //关闭保护模式,修改为no 
③注释公共配置端口port 6379
④修改为后台启动daemonize yes
⑤注释进程编号记录文件pidfile /var/run/redis_6379.pid
⑥注释公共配置日志文件logfile ""
⑦注释公共配置数据文件、修改数据文件路径
注释:dbfilename dump.rdb
修改:dir /opt/redis/data
⑧添加从服务器访问主服务器认证 masterauth root
⑨添加访问认证requirepass root
⑩注释公共配置追加文件appendfilename "appendonly.aof"
修改:appendonly no
⒒从服务器默认是只读不允许写操作(不用修改)slave-read-only yes

配置三个服务器的配置redis-6379.conf,redis-6380.conf,redis-6381.conf

#引用公共配置 
include /opt/redis/conf/redis-common.conf 
#进程编号记录文件 
pidfile /var/run/redis-6379.pid 
#进程端口号
port 6379 
#日志记录文件 
logfile "/opt/redis/log/redis-6379.log" 
#数据记录文件 
dbfilename dump-6379.rdb 
#追加文件名称 
appendfilename "appendonly-6379.aof" 
#下面的配置无需在6379里配置 
#备份服务器从属于6379推荐配置配局域网IP 
slaveof 192.168.10.100 6379

此处3679作为主服务器,其他两个只需要该端口号即可最后slaveof是从服务器指向主服务器地址的


② 启动测试
[root@localhost bin]# ./redis-server /opt/redis/conf/redis-6379.conf 
[root@localhost bin]# ./redis-server /opt/redis/conf/redis-6380.conf 
[root@localhost bin]# ./redis-server /opt/redis/conf/redis-6381.conf 

在这里插入图片描述


这里我们使用客户端连接,查看服务器状态,并在主服务添加,其余从服务器也会直接添加内容
在这里插入图片描述


在这里插入图片描述


2、主从复用

主要是对哨兵sentinel的配置:通过哨兵对主服务器的监听,每隔一段时间哨兵会对主服务器发送请求,主服务器在一定时间没有回应,一旦有两个以上的哨兵发现没有回应,则会进行从服务器选举,选出一个新的主服务器


①、配置

公共配置:sentinel-common.conf(从redis解压目录下复制sentinel.conf至/opt/redis/conf/)

cp sentinel.conf /opt/redis/conf/sentinel-common.conf

修改配置文件:

① 注释哨兵监听进程端口号port 26379
② 指示 Sentinel 去监视一个名为 master 的主服务器,这个主服务器的IP地址为 127.0.0.1,端
口号为6379,而将这个主服务器判断为失效至少需要1(一般设置为2)Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)
修改:sentinel monitor mymaster 192.168.10.100 6379 2
③ 设置master和slaves的密码
sentinel auth-pass mymaster root
④ Sentinel 认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds mymaster 10000
⑤ 若 sentinel 在该配置值内未能完成 failover 操作(即故障时master/slave自动切换),则认为本次 failover 失败。
sentinel failover-timeout mymaster 180000
⑥ 关闭保护模式,修改为no
protected-mode no
⑦ 修改为后台启动
daemonize yes

配置三个哨兵的配置文件sentinel-26379.conf,sentinel-26380.conf,sentinel-26381.conf

#引用公共配置 
include /opt/redis/conf/sentinel-common.conf 
#进程端口号 
port 26379 
#进程编号记录文件 
pidfile /var/run/sentinel-26379.pid 
#日志记录文件(为了方便查看日志,先注释掉,搭好环境后再打开) 
logfile "/opt/redis/log/sentinel-26379.log"

复制 sentinel-26379.conf 的内容至 sentinel-26380.conf , sentinel-26381.conf 并且修改其内容,将26379替换即可。


②、启动测试
[root@localhost bin]# ./redis-sentinel /opt/redis/conf/sentinel-26379.conf 

在这里插入图片描述


将主服务器杀死:
在这里插入图片描述


从服务器被选为主服务器
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每日小新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值