zoukankan      html  css  js  c++  java
  • java-redis理论及与springboot整合

    如果有新知识,需要完善的知识,本人表达错误的地方,等等。欢迎大家留言,一起进步。

    在博客 java-完整项目搭建 中有具体应用。

    章节目录:

      一:基础

      二:持久化

      三:架构

      四:搭建

      五:与springboot整合

    一:基础

      k.v形式,基于内存,支持多种类型。

      具体的参考网络上资料。

    二:持久化

      2.1 为什么持久化?

        redis是基于内存的数据库,所以在机器宕机,或者服务重启,内存数据就不在了,所以需要持久化到磁盘。

      2.2 一定要持久化吗?

        如果不持久化,那么就相当于要重新查数据,缓存数据了。

        如果持久化了,重启服务时候恢复了之前持久化的数据,那么redis就接着之前的继续使用了。

      2.3 怎么持久化?

         2.3.1 持久化的方式

          有两种:RDB(默认方式)与AOF(默认是关闭的)

          1:RDB方式(数据快照)

            1.1 在默认情况下,Redis 将数据快照保存在名字为 dump.rdb的二进制文件中,启动redis时候加载dump.rdb文件即可。

            1.2 执行方式

              1,阻塞方式(即 save ,阻塞Redis服务,无法响应客户端请求,好处是数据不丢失):

                 过程:客户端中发起save命令 -->

                    服务端停止客户端的服务请求,创建新的rdb文件,然后替换掉旧文件 -->

                    服务端恢复客户端的服务请求。

                   

              2,非阻塞方式(即 bgsave ,坏处是可能造成数据丢失)

                 过程:客户端发起bgsave命令 -->

                    服务端会 fork() (创建)一个子进程 -->

                    这个子进程开始创建rdb文件 -->

                    创建完成通知父进程 -->

                    父进程将新的rdb文件替换旧文件。

                    

                    

             1.3 执行策略

              1,自动(本质为bgsave)

                默认的配置(配置文件 redis.conf 中):(只要满足下面三个的任意一个就会执行持久化操作)

                  save 900 1

                  save 300 10

                  save 60 10000

                  创建rdb文件之后,时间计数器和次数计数器会清零。所以多个条件的效果不是叠加的。

                  说明:例如 save 60 1000,Redis要满足在60秒内至少有1000个键被改动,会自动保存一次;

              2,手动

                在客户端发起save,bgsave命令

              3,比较save,bgsave   

                save 不用创建新的进程,速度略快,但是会阻塞,不适合线上运行。

                bgsave 需要创建子进程,消耗额外的内存,但是是非阻塞,适合线上运行。

            1.4 优缺点        

              优点

                可以设置rdb文件的归档时间,可以恢复到不同的版本;

                单一的rdb文件,很容易远程传输,适合灾难恢复;

                恢复大数据集速度比AOF快;

              缺点

                会丢失最近写入、修改的而未能持久化的数据;

                fork过程较为耗时,会造成毫秒级客户端请求的延迟;

          

          2:AOF方式(日志的记录方式)

            2.1 默认文件appendonly.aof记录所有的写操作命令,在服务启动的时候使用这些命令就可以还原数据库,

               调整AOF持久化策略,可以在服务出现故障时,不丢失任何数据,也可以丢失一秒的数据。相对于RDB损失小得多

            2.2 执行机制

              1 AOF写入机制

                1.1:什么是写入机制:

                  日志先写入内存缓冲区(buffer),等buffer满了,或者执行fsync或fdatasync时写入磁盘appendonly.aof文件。所以如果内存缓冲区的数据未写入磁盘时宕机,

                那么就会数据丢失。

                1.2:写入磁盘的策略:(appendfsync选项控制,选项值有:always、everysec、no

                  always:(运行速度慢,不会产生数据丢失)

                    服务器写入一个指令就调用一次fdatasync,即写入磁盘。

                  everysec:(默认选项,运行速度快,如果宕机可能会丢失1s的数据)

                    服务器每1s就执行一次fdatasync。

                  no:(运行速度快,丢失数据有不确定性)

                    服务器不会主动调用fdatasync,由操作系统决定何时调用。  

              2 AOF重写机制

                2.1:什么是重写机制:

                  aof文件中会写入很多重复的命令,导致文件也会很大。重写机制会合并一些重复的命令,使用尽量少的命令记录。

                2.2:重写过程

                  首先fork(创建)一个子进程负责重写aof工作。

                  子进程创建一个临时文件用于写入aof信息。

                  父进程开辟一个内存缓冲区写入新的aof命令。

                  子进程重写好aof文件之后,会通知父进程,父进程再把缓冲区新的aof命令交由子进程写入新临时文件。新临时文件会替换旧临时文件。

                  注意:如果中途发生故障,可以通过redis-check-aof工具修复。

                2.3 重写机制触发方式

                  1,手动

                    客户端向服务端发出bgrewriteaof命令

                  2,自动(通过配置文件中选项,自动执行bgrewriteaof命令)

                    auto-aof-rewrite-min-size <size>:(触发AOF重写所需的最小体积)

                      只要在AOF文件的体积大于等于size时,才会考虑是否需要进行AOF重写,这个选项用于避免对体积过小的AOF文件进行重写

                    auto-aof-rewrite-percentage<percent>:(指定触发重写所需的AOF文件体积百分比)

                      实际上就是对AOF的一个扩容,即当aof达到一个程度没办法再进行压缩重写时候,就按照这个比例对AOF扩容           

                    举例:

                      auto-aof-rewrite-min-size 64mb    当AOF文件大于64MB时候,可以考虑重写AOF文件

                      auto-aof-rewrite-percentage 100     只有当AOF文件的增量大于起始size的100%时(就是文件大小翻了一倍),启动重写

                      appendonly  no  或者 yes        默认关闭,请开启

            2.3 优缺点      

              优点:

                写入机制,默认fysnc每秒执行,性能很好不阻塞服务,最多丢失一秒的数据;

                重写机制,优化AOF文件;

              缺点:

                相同数据集,AOF文件体积较RDB大很多;

                恢复数据库速度叫RDB慢(文本,命令重演);

                开启AOF操作后,默认不再使用RDB作为备选,但二者仍然可以同时开启;

    三:架构(2.0版本架构与3.0版本架构)

      1:2.0版本架构(主从架构)

        1.1 角色  

          主节点(master):增删改查(指的是处理客户端请求)

          从节点(slaves):查(可以处理客户端的查询请求)

          高可用(Sentinel  哨兵):实现主从的转换等,可以监控多个集群,哨兵需要做HA

        1.2 集群配置:参考网络资料

        1.3 哨兵搭建

          1.3.1:Sentinel 配置文件说明:

            port 26379  //哨兵默认的端口号是26379

            sentinel monitor mymaster 127.0.0.1 6379 2    //sentinel monitor哨兵监控

                                  //mymaster 要监控的集群名称(随便起的,用来区分)

                                  //127.0.0.1 6379监控的master

                                  //2两个哨兵同意才重新选举master

          1.3.2:Sentinel 配置举例

              1 cp src/redis-sentinel  redis/bin  //将redis的哨兵执行文件cp到bin下

              2 创建目录,在目录下创建配置文件(此处创建3个哨兵,需要3个配置文件)

                找个目录下创建sentinel1.conf,sentinel2.conf,sentinel3.conf:

                sentinel1.conf的内容为:

                  port 26379

                  Sentinel monitor s1 127.0.0.1 6380 2  //哨兵监控s1这个集群的6380的这个,2个哨兵同意之后就可以主从切换

                sentinel2.conf的内容为:

                  Port 26380

                  Sentinel monitor s1 127.0.0.1 6380 2

                Sentinel3.conf的内容为:

                  Port 26381

                  Sentinel monitor s1 127.0.0.1 6380 2

              3 启动redis集群(到创建三个配置文件的目录下)

                $redis-sentinel sentinel1.conf

                $redis-sentinel sentinel2.conf

                $redis-sentinel sentinel3.conf

        1.4 存在的问题

          问题1:从节点掉线,读能力下降

          问题2:主节点掉线,写能力缺失(解决:可以使用哨兵)

          问题3:只有一个主节点才有写的能力,所以写的性能是个问题

              解决思路:让多个节点处理。

              使用:twemproxy(代理模式,具体可以查询网络资料,本人觉得3.0版本架构更胜一筹)。

      2:3.0版本架构(集群架构)

        2.1 架构

          由多个节点的redis集群组成,每个节点上都有master(用于存储数据)与slave(是master的复制品,可以有多个副本)

          

          图中:7000 7001 7002为主节点,7003 7004 7005为相对应的复制节点    

          问题:如果7000掉线,怎么切换到7003的呢?这里就不用sentinel(哨兵)了,由集群中其他master决定,即7001 7002。

        2.2 数据存储方式(槽位的形式,分担了数据写的压力)

            集群分片说明:Slot(槽位),集群将整个数据库分为16384个槽位,有多少个集群节点,就会来平分这些槽位。

     

            举个栗子:有个数据进来了,那么我们去到key值,通过公式 crc16(key)%16384 (crc16为16位的循环冗余校验和函数,我也不懂...,就是一个函数),

                 来计算出槽位,然后找个处理这个数据对应的节点是哪个。

    四:搭建(搭建版本3.0版本)

      1 安装与环境:

        1、创建目录redis-cluster,在redis-cluster下解压安装redis3.0(tar xf redis.....gz);

        2、在redis的目录下安装redis3.0(make && make PREFIX=/opt/redis install)意思是将redis安装到/opt/redis目录下;

        3、安装ruby编译环境(ruby脚本进行槽位的分发

          # yum -y install ruby rubygems

        4、在redis-cluster安装目录下安装 redis gem 模块(安装gem块进行槽位分发)

          # gem install --local redis-3.3.0.gem(生成出 redis-trib.rb 文件)

     

      2 搭建:

        5、创建配置文件 redis.conf :

          步骤:

            mkdir cluster-test

            cd cluster-test

            mkdir 7000 7001 7002 7003 7004 7005

            在7000-7005每个目录中均放入redis的redis.conf

              redis.conf内容如下:

                cluster-enabled yes  //集群方式集群

                port 700X //这台的端口

          说明:

            指定3个主节点端口为7000、7001、7002,对应的3个从节点端口为7003、7004、7005

         5、创建配置文件redis.conf(启集群模式: 3.0 支持单机集群,但必须在配置文件中说明) (已完成)

          指定不冲突的端口 及 <对应端口号>

          文件内容:

            声明支持集群模式,指定端口:

              在7000-7005每个目录中均放入redis.conf

              redis.conf内容如下:

                cluster-enabled yes  //集群方式集群

                port 700X //这台的端口

        6、创建集群,槽位认领

          在安装目录下的src中,找到 redis-trib.rb 这是rubby脚本执行程序,完成redis3.0集群创建

          # ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

          执行之后,自动分配了主从,自动分配了slots,所有槽都有节点处理,集群状态上线

        7、6个实例分别读取6个配置文件(启动redis)

          # cd 700x

          # redis-server redis.conf

         8、查看运行状态

          # ss -tanl | grep 700  

        9、客户端连接(一般应用是整合springboot使用)

          # redis-cli -p 7000 -c

    五:与springboot整合

      1:jar包依赖(使用RedisTemplate工具包)

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

      2:application.properties文件配置

    # Redis数据库索引(默认为0)
    spring.redis.database=0  
    # Redis服务器地址
    spring.redis.host=127.0.0.1
    # Redis服务器连接端口
    spring.redis.port=6379  
    # Redis服务器连接密码(默认为空)
    spring.redis.password=
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=8  
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1  
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=8  
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0  
    # 连接超时时间(毫秒)
    spring.redis.timeout=0  

       3:在@configuration中定义bean,可自定义连接工厂JedisConnectionFactory。

        设置连接的集群,序列化设置等。(具体设置参考网络资料)

      4:使用@Component创建工具类(这里只写引入redisTemplate方式)

    @Component
    public class RedisService {
        //方式1:自动装配,使用时候需要创建对象
        @Autowired
        private RedisTemplate<String, String> stringRedisTemplate;
        //方式2:创建静态的,使用时候直接使用即可
        private static RedisTemplate<String, Object> objectRedisTemplate;
        @Autowired //方法名称是随意的
        public void setObjectRedisTemplate(ObjectRedisTemplate objectRedisTemplate){
           this.objectRedisTemplate = objectRedisTemplate;
        }
    }

        

  • 相关阅读:
    hashmap的一些基础原理
    关于uuid
    读锁跟写锁的区别
    栈为什么效率比堆高
    MySQL行级锁、表级锁、页级锁详细介绍
    MYSQL MyISAM与InnoDB对比
    MYSQL锁表问题解决
    mysql查询锁表语句
    三种排序方法
    正则表达式
  • 原文地址:https://www.cnblogs.com/dblog/p/12202662.html
Copyright © 2011-2022 走看看