Day_14 Redis

01-秒杀案例解决库存遗留问题(掌握)

  • 概述

    ab -n 1000 -c 200 -p /usr/local/data.txt -T "application/x-www-form-urlencoded" 192.168.12.62:8080/doSeckill
    
    • ab -n 1000 : 有1000个人在秒杀商品
    • ab -n 1000 -c 200 : 有1000个人在秒杀商品,允许200个人同时抢1件商品,意味着虽然有1000个人在秒杀,但是只能卖出5件商品.这就是所谓的库存遗留问题.
  • 解决方案

    • 将并发请求变成一个请求,使用LUA脚本.
  • LUA脚本

    • 将复杂的或者多步的redis操作,写为一个脚本,一次提交给redis执行,减少反复连接redis的次数。 提升性能。
    • LUA脚本是类似redis事务,有一定的原子性,不会被其他命令插队,可以完成一些redis事务性的操 作。
  • 代码实现

    public class SeckillLUAUtils {
    
        //将之前的多次请求,使用LUA脚本拼接成一次请求
        private static String secKillScript = "local userid=KEYS[1];\r\n" +
                "local prodid=KEYS[2];\r\n" +
                "local qtkey='seckill:'..prodid..\":kc\";\r\n" +
                "local usersKey='seckill:'..prodid..\":user\";\r\n" +
                "local userExists=redis.call(\"sismember\",usersKey,userid);\r\n" +
                "if tonumber(userExists)==1 then \r\n" +
                "   return 2;\r\n" +
                "end\r\n" +
                "local num= redis.call(\"get\" ,qtkey);\r\n" +
                "if tonumber(num)<=0 then \r\n" +
                "   return 0;\r\n" +
                "else \r\n" +
                "   redis.call(\"decr\",qtkey);\r\n" +
                "   redis.call(\"sadd\",usersKey,userid);\r\n" +
                "end\r\n" +
                "return 1";
    
        public static boolean doSeckill(String uid, String prodid) throws IOException {
            Jedis jedis = JedisUtils.getJedis();
            String sha1 = jedis.scriptLoad(secKillScript);
            Object result = jedis.evalsha(sha1, 2, uid, prodid);
            String reString = String.valueOf(result);
            if ("0".equals(reString)) {
                System.out.println("失败!秒杀已经结束!");
                return false;
            } else if ("1".equals(reString)) {
                System.out.println("抢购成功!!!!");
            } else if ("2".equals(reString)) {
                System.out.println("失败!您已经秒杀成功过了!把机会给别人吧!");
                return false;
            } else {
                System.err.println("抢购异常!!");
                return false;
            }
            jedis.close();
            return true;
        }
    }
    

02-主从复制概述(掌握)

  • 概述
    • 现象1:硬盘故障、系统崩溃 ,
    • 现象2:内存不足,从16G升级到64G,从64G升级到128G,无限升级内存
    • 会放弃使用redis
  • 解决方案
    • image-20220412094051275
    • master 数据提供方、写数据 主服务器、主节点、主库
    • slave 数据接收方、读数据 从服务器、从节点、从库
  • 主从复制
    • 主从复制就是将master中的数据及时地、有效地复制到slave中
    • 一个master可以拥有多个slave,一个slave只对应一个master
  • 好处
    • 读写分离
      • master写、slave读,提高服务器的读写负载能力
    • 负载均衡
      • 基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数 量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
    • 故障恢复
      • 当master出现问题时,由slave提供服务,实现快速的故障恢复
    • 数据冗余
      • 实现数据热备份,是持久化之外的一种数据冗余方式
    • 高可用基石
      • 基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案

03-主从复制搭建(掌握)

  • 需求

    • 搭建1主1从的主从结构
  • master主机

    port 6379
    
    daemonize no
    
    dir "/usr/local/redis-6379/data"
    
    # 设置RDB文件
    dbfilename "dump-6379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-6379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
  • slave从机

    port 26379
    
    daemonize no
    
    dir "/usr/local/redis-26379/data"
    
    # 设置RDB文件
    dbfilename "dump-26379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-26379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    
    slaveof 192.168.148.110 6379
    
  • 执行流程

    • ①建立链接阶段
    • ②数据同步阶段
    • ③命令传播阶段

04-主从复制之建立链接阶段(掌握)

  • 建立连接
    • image-20220412102341425

05-主从复制之数据同步阶段(掌握)

  • 数据同步
    • image-20220412102540595

06-部分复制的三个核心要素(掌握)

  • 三个核心要素
    • ①服务器运行id(run id)
    • ②主服务器的复制缓冲区
    • ③主从服务器的复制偏移量
  • ①服务器运行id(run id)
    • 服务器运行id是每一台服务器每次运行的身份识别码,一台服务器多次运行可以生成多个运行id,用于在 服务器之间进行传输识别身份
  • ②主服务器的复制缓冲区
    • image-20220412104256958
  • ③主从服务器的复制偏移量
    • master复制偏移量:记录发送给所有slave的指令字节对应的位置(多个)
    • slave复制偏移量:记录slave接收master发送过来的指令字节对应的位置(一个

07-主从复制之命令传播阶段(掌握)

  • 概述
    • 当master数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致 的状态,同步的动作称为命令传播
    • master将接收到数据变更命令发送给slave,slave接收命令后执行
  • 断网现象
    • 网络闪断闪连,可以忽略
    • 短时间网络中断,部分复制
    • 长时间网络中断,全量复制

08-哨兵模式概述(掌握)

  • 在主从复制中,如果master宕机了,怎么办?
    • 关闭master和所有slave
    • 选举一个slave作为master
    • 修改其他slave配置,连接新的master,启动新的master与slave
  • 存在问题
    • 关闭期间的数据服务谁来负责?
    • 怎么选举?
    • 原来的master恢复了怎么办?
  • 哨兵模式
    • image-20220412111749495
    • sentinel是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制 选择新的master并将所有slave连接到新的master。
  • 作用
    • 监控:监控master和slave
    • 通知(提醒)
    • 自动故障转移

09-哨兵模式配置(掌握)

  • 需求

    • 1主2从3哨兵
  • 哨兵语法

    # 设置哨兵监听的主服务器信息,
    # sentinel_number表示参与投票的哨兵数量,哨兵总数量的一半加1
    sentinel monitor <master_name> <master_host> <master_port> <sentinel_number>
    
    # 设置判定服务器宕机时长,该设置控制是否进行主从切换,单位:毫秒
    sentinel down-after-milliseconds <master_name> <million_seconds>
    
    # 设置故障切换的最大超时时间,单位:毫秒
    sentinel failover-timeout <master_name> <million_seconds>
    
    # 设置主从切换后,同时进行数据同步的slave数量,数值越大,要求网络资源越高,同步时间越长
    sentinel parallel-syncs <master_name> <sync_slave_number>
    
  • 开发步骤

    • ①配置1个主机
      • redis-6379
    • ②配置2个从机
      • redis-26379 , redis-26380
    • ③配置3个哨兵
      • redis-36379 , redis-36380 , redis-36381
  • ①配置1个主机

    port 6379
    daemonize no
    dir "/usr/local/redis-6379/data"
    
    # 设置RDB文件
    dbfilename "dump-6379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-6379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
  • ②配置2个从机

    port 26379
    daemonize no
    dir "/usr/local/redis-26379/data"
    
    # 设置RDB文件
    dbfilename "dump-26379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-26379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    slaveof 192.168.148.110 6379
    
    port 26380
    daemonize no
    dir "/usr/local/redis-26380/data"
    
    # 设置RDB文件
    dbfilename "dump-26380.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-26380.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    slaveof 192.168.148.110 6379
    
  • ③配置3个哨兵

    port 36379
    daemonize no
    dir /usr/local/redis-36379/data
    
    # 设置哨兵监控的master信息:host、port、参与投票的哨兵数量
    sentinel monitor mymaster  192.168.148.110 6379 2
    
    # master宕机5秒后,进行主从切换
    sentinel down-after-milliseconds mymaster 5000
    
    # master宕机3分钟后,如果主从切换还没成功,那么就彻底失败
    sentinel failover-timeout mymaster 180000
    
    # 主从切换后,数据同步的从机数量为1
    sentinel parallel-syncs mymaster 1
    
    # 主从切换过程中,如果有问题发生,那么就终止切换
    sentinel deny-scripts-reconfig yes
    
    
    port 36380
    daemonize no
    dir /usr/local/redis-36380/data
    
    # 设置哨兵监控的master信息:host、port、参与投票的哨兵数量
    sentinel monitor mymaster  192.168.148.110 6379 2
    
    # master宕机5秒后,进行主从切换
    sentinel down-after-milliseconds mymaster 5000
    
    # master宕机3分钟后,如果主从切换还没成功,那么就彻底失败
    sentinel failover-timeout mymaster 180000
    
    # 主从切换后,数据同步的从机数量为1
    sentinel parallel-syncs mymaster 1
    
    # 主从切换过程中,如果有问题发生,那么就终止切换
    sentinel deny-scripts-reconfig yes
    
    
    port 36381
    daemonize no
    dir /usr/local/redis-36381/data
    
    # 设置哨兵监控的master信息:host、port、参与投票的哨兵数量
    sentinel monitor mymaster  192.168.148.110 6379 2
    
    # master宕机5秒后,进行主从切换
    sentinel down-after-milliseconds mymaster 5000
    
    # master宕机3分钟后,如果主从切换还没成功,那么就彻底失败
    sentinel failover-timeout mymaster 180000
    
    # 主从切换后,数据同步的从机数量为1
    sentinel parallel-syncs mymaster 1
    
    # 主从切换过程中,如果有问题发生,那么就终止切换
    sentinel deny-scripts-reconfig yes
    
    

10-哨兵模式演示(掌握)

  • 开发步骤
    • ①启动1个主机
      • redis-6379
    • ②启动2个从机
      • redis-26379 , redis-26380
    • ③启动3个哨兵
      • redis-36379 , redis-36380 , redis-36381
    • ④查看哨兵信息
      • 在主机的客户端查看
      • 在从机的客户端查看
      • 在哨兵的客户端查看
    • ⑤演示主从切换
      • 关闭redis-6379
  • ①启动1个主机
    • redis-server /usr/local/redis-6379/redis-6379.conf
    • image-20220412140732441
  • ②启动2个从机
    • redis-server /usr/local/redis-26379/redis-26379.conf
    • image-20220412140911238
    • redis-server /usr/local/redis-26380/redis-26380.conf
    • image-20220412141044409
  • ③启动3个哨兵
    • redis-sentinel /usr/local/redis-36379/redis-36379.conf
    • image-20220412141231957
    • redis-sentinel /usr/local/redis-36380/redis-36380.conf
    • image-20220412141325614
    • redis-sentinel /usr/local/redis-36381/redis-36381.conf
    • image-20220412141405510
  • ④查看哨兵信息
    • image-20220412141825320
    • image-20220412141836494
    • image-20220412141846536
  • ⑤演示主从切换
    • image-20220412143501731

11-哨兵模式工作流程(掌握)

  • 工作流程
    • 监控
      • 用于同步各个节点(master、slave、sentinel)的状态信息
    • 通知
      • 用来保持联通,发现故障
    • 故障转移
      • 发现老的master挂了
      • 竞选哨兵负责人
      • 优选新的master
      • 新master上任,其它slave切换master,原master作为slave故障恢复后连接
  • 监控
    • image-20220412143906460
  • 通知
    • image-20220412144053749
  • 故障转移
    • image-20220412144508168
    • image-20220412144521468
    • image-20220412144533332

12-Cluster集群概述(掌握)

  • 存在问题?
    • redis提供的服务OPS(operation per second)可以达到10万/秒,当前业务OPS如果超过10万/秒, 怎么办?
    • 内存单机容量达到256G,当前业务需求内存容量1T,怎么办?
  • cluster集群
    • image-20220412151439596
  • 作用
    • 分散单台服务器的访问压力,实现负载均衡
    • 分散单台服务器的存储压力,实现可扩展性
    • 降低单台服务器宕机带来的业务灾难

13-Cluster集群配置及启动(掌握)

  • 需求

    • 搭建3个1主1从的主从结构,并启动集群.
  • 集群语法

    # 是否启用cluster,加入cluster节点
    cluster-enabled yes|no
    # cluster配置文件名,该文件属于自动生成,仅用于快速查找文件并查询文件内容
    cluster-config-file filename
    # 节点服务响应超时时间,用于判定该节点是否下线或切换为从节点
    cluster-node-timeout milliseconds
    
    
    #<master-host1>:<master-port1> ... <master-hostn>:<master-portn> : 主机的ip和port
    #<slave-host1>:<slave-port1> ... <slave-hostn>:<slave-portn> : 从机的ip和port
    #--cluster-replicas <n> : 1个master对应n个slave
    redis-cli --cluster create 
    <master-host1>:<master-port1> ... <master-hostn>:<master-portn> 
    <slave-host1>:<slave-port1> ... <slave-hostn>:<slave-portn> 
    --cluster-replicas <n>
    
    
  • 开发步骤

    • ①配置3个主机
      • redis-6379 , redis-6380 , redis-6381
    • ②配置3个从机
      • redis-26379 , redis-26380 , redis-26381
    • ③启动3个主机,3个从机
    • ④启用cluster集群服务
    • ⑤查看cluster集群信息
  • ①配置3个主机

    port 6379
    
    daemonize no
    
    dir "/usr/local/redis-6379/data"
    
    # 设置RDB文件
    dbfilename "dump-6379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-6379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    # 开启集群
    cluster-enabled yes
    # cluster配置文件名
    cluster-config-file "cluster-6379.conf"
    # 节点服务响应超时时间为5秒
    cluster-node-timeout 5000
    
    
  • ②配置3个从机

    # 6379的slave
    
    port 26379
    
    daemonize no
    
    dir "/usr/local/redis-26379/data"
    
    # 设置RDB文件
    dbfilename "dump-26379.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-26379.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    # 开启集群
    cluster-enabled yes
    # cluster配置文件名
    cluster-config-file "cluster-26379.conf"
    # 节点服务响应超时时间为5秒
    cluster-node-timeout 5000
    
    
  • ③启动3个主机,3个从机

    • redis-server /usr/local/redis-6379/redis-6379.conf
    • redis-server /usr/local/redis-26379/redis-26379.conf
  • ④启用cluster集群服务

    redis-cli --cluster create 192.168.148.110:6379 192.168.148.110:6380 192.168.148.110:6381 192.168.148.110:26379 192.168.148.110:26380 192.168.148.110:26381 --cluster-replicas 1
    
    
    • image-20220412153809011
  • ⑤查看cluster集群信息

    • image-20220412154412756
    • image-20220412154427846

14-Cluster集群演示(掌握)

  • ①使用集群操作set指令

    #普通模式,不能适用于集群
    redis-cli 
    set name oldqiu
    get name
    
    
    #集群模式
    redis-cli -c
    set name oldqiu
    get name
    
    
  • ②使用集群演示主从转换

    • Cluster集群内置了哨兵模式

15-Cluster集群添加master节点(掌握)

  • 需求

    • 将redis-6382作为新主机添加到集群
  • 语法

    #<newhost>:<newport>:新主机的ip和port
    #<clusterhost>:<clusterport> : 已经在集群的主机的ip和port
    redis-cli --cluster add-node 
    <newhost>:<newport>
    <clusterhost>:<clusterport>
    
    
  • 开发步骤

    • ①启动新的主机
      • redis-6382
    • ②将redis-6382添加到集群
  • ①启动新的主机

    port 6382
    
    daemonize no
    
    dir "/usr/local/redis-6382/data"
    
    # 设置RDB文件
    dbfilename "dump-6382.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-6382.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    # 开启集群
    cluster-enabled yes
    # cluster配置文件名
    cluster-config-file "cluster-6382.conf"
    # 节点服务响应超时时间为5秒
    cluster-node-timeout 5000
    
    
    redis-server /usr/local/redis-6382/redis-6382.conf
    
    
  • ②将redis-6382添加到集群

    redis-cli --cluster add-node 192.168.148.110:6382 192.168.148.110:6379
    
    
  • ③查看cluster集群信息

16-Cluster集群添加slave节点(掌握)

  • 需求

    • 将redis-26382作为redis-6382的从机添加到集群
  • 语法

    #<new-slave-host>:<new-slave-port> : 新从机的ip和port
    #<master-host>:<master-port> : 主机的ip和port
    #<master-id> : 主机的id
    redis-cli --cluster add-node
    <new-slave-host>:<new-slave-port>
    <master-host>:<master-port>
    --cluster-slave --cluster-master-id <master-id>
    
    
  • 开发步骤

    • ①启动从机
      • redis-26382
    • ②将redis-26382添加到集群
    • ③查看cluster集群信息
  • ①启动从机

    # 6379的slave
    
    port 26382
    
    daemonize no
    
    dir "/usr/local/redis-26382/data"
    
    # 设置RDB文件
    dbfilename "dump-26382.rdb"
    
    # 开启aof
    appendonly yes
    appendfilename "appendonly-26382.aof"
    appendfsync everysec
    
    
    # 设置无密码访问
    protected-mode no
    
    
    # 开启集群
    cluster-enabled yes
    # cluster配置文件名
    cluster-config-file "cluster-26382.conf"
    # 节点服务响应超时时间为5秒
    cluster-node-timeout 5000
    
    
    redis-server /usr/local/redis-26382/redis-26382.conf
    
    
  • ②将redis-26382添加到集群

    redis-cli --cluster add-node 192.168.148.110:26382 192.168.148.110:6382 --cluster-slave --cluster-master-id d6535c1c2e2bca5eeac585b123b101dee019ba00
    
    
  • ③查看cluster集群信息

17-Cluster集群移除节点(掌握)

  • 语法

    #<node-host>:<node-port> <node-id> : 节点的ip和port,id
    redis-cli --cluster del-node <node-host>:<node-port> <node-id>
    
    
  • 需求

    • ①移除redis-26382
    • ②移除redis-6382
  • 代码实现

    redis-cli --cluster del-node 192.168.148.110:26382 8048d65a162fa7be45a12dc21622075d8ac4cf19
    
    
    redis-cli --cluster del-node 192.168.148.110:6382 d6535c1c2e2bca5eeac585b123b101dee019ba00
    
    

18-Cluster集群分槽(掌握)

  • 概述

    • redis总共有16384个槽,需要分配给对应master主机.
  • 语法

    #<target-master-host>:<target-master-port> : 目标主机的ip和port
    #<source-master-id1> ... <source-master-idn> : 源主机的id
    #<target-master-id> : 目标主机的id
    #<n>:分配n个槽
    redis-cli --cluster reshard
    <target-master-host>:<target-master-port>
    --cluster-from <source-master-id1> ... <source-master-idn>
    --cluster-to <target-master-id>
    --cluster-slots <n>
    
    
  • 需求

    • 将redis-6379 , redis-6380 ,redis-6381的4096个槽分配给redis-6382
  • 代码实现

    redis-cli --cluster reshard 192.168.148.110:6382 --cluster-from 38f366d6ff8af4bf8cfceba5bec440d653473a6f ab178720e72231d54d9d877f032c1eb855c54e32 57068d471add84cd4218f9b0055a804e5167e785 --cluster-to d6535c1c2e2bca5eeac585b123b101dee019ba00 --cluster-slots 4096
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值