南七星之家 发表于 2024-6-15 02:32:43

redis

1.Redis简介

   Remote Dictionary Server(长途字典服务器),是一个用C语言编写的、开源的、基于内存运行并支持持久化的、高性能的NoSQL数据库.也是当前热门的NoSQL数据库之一。
2.Redis的特点


[*]支持数据持久化。Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
[*]支持多种数据结构。Redis不仅仅支持简单的key-value范例的数据,同时还提供list,set,zset,hash等数据结构的存储。
[*]支持数据备份。Redis支持数据的备份,即master-slave模式的数据备份。
3.redis的启动和关闭方式


[*]开启


[*]前台启动:redis-server
https://img-blog.csdnimg.cn/direct/74f4e3893d4249e4894a04507d1500fc.png
关闭此窗口,redis服务关闭
[*]背景启动:redis-server &
[*]根据配置文件启动 启动命令 配置文件 &:redis-server & 配置文件

[*]关闭


[*]恣意目录下实行 指令redis-cli shutdown(推荐)
[*]kill pid 或者 kill -9 pid
4.Key相干操纵

命令说明keys *检察当前库所有 keyexists key判定某个 key 是否存在type key检察key对应的范例del key删除指定的 key 数据unlink key根据 value 选择非阻塞删除(异步删除)expire key seconds为给定的 key 设置过期时间.(单元:秒)ttl key检察另有多少秒过期,-1 表示永不过期,-2 表示已过期select切换数据库(一共16个数据库,select+数字)dbsize检察当前数据库的 key 的数量flushdb清空当前库 5.redis字符串(String)操纵

命令说明set key value设置键值对mset k1 v1 k2 v2…同时设置一个或多个 key-value对setnx key value只有在 key 不存在时设置 key 的值msetnx k1 v1 k2 v2…同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在setex key 过期时间 value设置键值的同时,设置过期时间,单元秒strlen key获取值的长度append key value将给定的value追加到原值的末了,incr key将 key 中储存的数字值增 1,只能对数字值操纵,如果为空,新增值为 1decr key将 key 中储存的数字值减 1,只能对数字值操纵,如果为空,新增值为-1incrby / decrby key step将 key 将 key 中储存的数字值增减。自定义步长get key查询对应键值mget k1 k2 k3…同时获取一个或多个 valuegetrange key 起始位置 竣事位置获得值的范围,类似 java 中的 substring,前包,后包get key value以新换旧,设置了新值同时获得旧值 6.redis列表(List)操纵

   Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层现实是个双向链表,对两头的操纵性能很高通过索引下标的操纵中间的节点性能会较差
https://img-blog.csdnimg.cn/direct/17e97726f5a348788d61663b4158966b.png
命令说明lpush key v1 v2 v3 …从左边/右边插入一个或多个值lpop/rpop key从左边/右边吐出一个值(值在键在,值光键亡)rpoplpush key1 key2从key1列表右边吐出一个值,插到key2列表左边lrange key start stop按照索引下标获得元素(从左到右)lindex key index按照索引下标获得元素(从左到右)llen key获得列表长度linsert key before/after value newvalue在value的前面/后面插入newvalue插入值lrem key n value从左边删除n个 value(从左到右)lset key ndex value将列表 key 下标为 index的值替换成 value 7. redis聚集(set)操纵

   Redis set对外提供的功能与 1ist 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判定某个成员是否在一个 set聚集内的紧张接口,这个也是 1ist所不能提供的。
指令说明sadd key value1 value2将一个或多个 member 元素参加到聚集 key 中,已经存在的 member 元素将被忽略smembers key取出该聚集的所有值sismember key value判定聚集key是否为含有该value值,有1,没有 0.scard key返回该聚集的元素个数srem key value1 value2删除聚会合的某个元素spop key随机从该聚会合吐出一个值srandmember key n随机从该聚会合取出n个值。不会从聚会合删除smove <source> <destination>value把聚会合一个值从一个聚集移动到另一个聚集sinter key1 key2返回两个聚集的交集元素sunion key1 key2返回两个聚集的并集元素sdiff key1 key2返回两个聚集的差集元素(key1 中的,不包含 key2 中的) 8.redis哈希(hash)操纵

   Redis hash 是一个键值对聚集,Redis hash 是一个 strimng范例的 field 和 value 的映射表,hash 特别适合用于存储对象,。类似 Java 里面的 Map<String.object>,用户 ID 为查找的 key,存储的 value用户对象包含姓名,年事,生日等信息,如果用普通的 key/value 结构来存储。
指令说明hset key filed value给key聚会合的field键赋valuehget key field从key1聚集field取出 valuehmset key field1 valuel field2 value2批量设置 hash 的值hexists key field査看哈希表 key 中,给定域 field 是否存在hkeys key列出该 hash 聚集的所有 fieldhvals key列出该 hash 聚集的所有 valuehincrby key field increment为哈希表 key 中的域 field 的值加上增量 1 -1hsetnx key field value将哈希表 key 中的域 field 的值设置为 value,当且仅当域field 不存在 9.redis有序聚集(zset)操纵

   Redis 有序聚集 zset 与普通聚集 set 非常相似,是一个没有重复元素的字符串聚集。差别之处是有序聚集的每个成员都关联了一个评分(spore),这个评分(score)被用来按照从最低分到最高分的方式排序聚会合的成员。聚集的成员是唯一的,但是评分可以是重复的,因为元素是有序的,以是你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序聚集的中间元素也是非常快的,因此你可以或许使用有序聚集作为一个没有重复成员的智能列表。.
指令说明zadd key score1 value1 score2 value2…将一个或多个 member 元素及其 score 值参加到有序集 key 当中zrange key start stop 返回有序集 key 中,下标在start stop之间的元素,带 WITHSCORES,可以让分数一起和值返回到结果集zrangebyscore key min max 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包罗等于 min 或 max )的成员.有序集成员按 score 值递增(从小到大)次序排列zrevrangebyscore key max min 同上,改为从大到小排列zincrby key increment value为元素的 score 加上增量zrem key value删除该聚集下,指定值的元素zcount key min max统计该聚集,分数区间内的元素个数zrank key value返回该值在聚会合的排名,从0开始 10.redis发布订阅

   Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅恣意数量的频道。

[*]客户端订阅信息
https://img-blog.csdnimg.cn/direct/fc227a3ce6e442a5a67d5c084d94f204.png
[*]服务端发布消息
https://img-blog.csdnimg.cn/direct/5ac81a6e4a794ec6a0ab14d29e404975.png


[*]redis订阅信息:SUBSCRIBE channe1
https://img-blog.csdnimg.cn/direct/396f42b1b25647dea3f215031a43bb6d.png
[*]redis发布信息:publish channe message
https://img-blog.csdnimg.cn/direct/5238ef0a318045dd8f47863738162a99.png
https://img-blog.csdnimg.cn/direct/14242e4a33604b038c5a7bf770250874.png
11.redis新增的数据范例

10.1Bitmaps



[*]Bitmaps 本身不是一种数据范例, 现实上它就是字符串(key-value) , 但是它可以对字符串的位进行操纵
[*]Bitmaps 单独提供了一套命令, 以是在 Redis 中使用 Bitmaps 和使用字符串的方法不太雷同。 可以把 Bitmaps 想象成一个以位为单元的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。
https://img-blog.csdnimg.cn/direct/56765fbc52584297825832f44a8404b6.png

[*]setbit key offset value设置Bitmaps中某个偏移量的值(0或1),offset从0开始
https://img-blog.csdnimg.cn/direct/a9aa1737f06748e09d0b745546388603.png
[*]getbit key offset获取Bitmaps中某个偏移量的值
https://img-blog.csdnimg.cn/direct/7f0f24f3378d46f4a24ae7687b16072f.png
[*]bitcount key 统计字符串从 start 字节到 end 字节比特值为 1的数量
https://img-blog.csdnimg.cn/direct/2326ecfad50f437eaf76829b2ab92f9e.png
10.2HyperLogLog

   在工作当中,我们常常会碰到与统计相干的功能需求,比如统计网站 PV(PageView 页面访问量),可以使用 Redis 的 incr、incrby 轻松实现。但像 UV(UniqueVisitor 独立访客)、独立 IP 数、搜刮记录数等需要去重和计数的题目如何解决?这种求聚会合不重复元素个数的题目称为基数题目。解决基数题目有很多种方案:


[*]数据存储在 MySQL 表中,使用 distinct count 计算不重复个数
[*]使用 Redis 提供的 hash、set、bitmaps 等数据结构来处理。
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切现实的。能否可以或许降低一定的精度来均衡存储空间?Redis 推出了 HyperLogLog。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8},那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数 (不重复元素) 为 5。 基数估计就是在误差可继承的范围内,快速计算基数。

[*]pfadd key element 添加指定元系到 HyperLogLog 中
[*]pfcount key 计算 HLL 的近似基数,可以计算多个 HLL,比如用 HLL 存储每天的 UV,计算一周的 UV 可以使用7天的 UV 合并计算即可
https://img-blog.csdnimg.cn/direct/aa5fbbde3b074b8db965cefcb4df00e6.png
[*]pfmerge destkey sourcekey 将一个或多个 HLL 合并后的结果存储在另一个 HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得。
https://img-blog.csdnimg.cn/direct/d2b5cad71f844fc8927cb6475865f2e0.png
10.3Geospatial

   Redis 3.2 中增加了对 GEO 范例的支持。GEO,Geographic,地理信息的缩写。该范例,就是元素的 2 维坐标,在舆图上就是经纬度。redis 基于该范例,提供了经纬度设置,查询,范围查询,间隔查询,经纬度 Hash 等常见操纵。

[*]geoadd key longitde latitude member添加地理位置(经度,纬度,名称)
https://img-blog.csdnimg.cn/direct/4f82c756ad03455ca4975b00472dfede.png
[*]geopos key member 获得指定地区的坐标值
https://img-blog.csdnimg.cn/direct/d1586f6d8f0c41e290f036b439d19541.png
[*]geodist key member1 member2 获取两个位置之间的直线间隔


[*]m 表示单元为米[默认值]
[*]km 表示单元为千米
[*]mi 表示单元为英里
[*]t 表示单元为英尺
https://img-blog.csdnimg.cn/direct/ab6bd5ce338f4265963ee38c38e627b2.png

[*]georadius key longitude latiitude raduis m|km|ft|mi以给定的经纬度为中心找出某一半径内的元素
https://img-blog.csdnimg.cn/direct/d1f80ec2e6a24224828018c7985d0be4.png
11.Jedis

   Jedis是使用java来操纵redis数据库,与jdbc类似
java操纵redis是使用Jedis对象进行操纵的:
https://img-blog.csdnimg.cn/direct/97ea2b181c5d4f6298bcee6b1d1b682e.png
使用Jedis在项目中引入依赖库:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
通过对象方法操纵redis:
public class JedisTest {
    public static void main(String[] args) {
      Jedis jedis = new Jedis("127.0.0.1", 6379);
      //测试是否成功连接redis
      String ping = jedis.ping();
      System.out.println(ping);//PONG:已连接成功
    }

    @Test
    public void testHash() {
      Jedis jedis = new Jedis("127.0.0.1", 6379);
      jedis.hset("user", "age", "20");
      String age = jedis.hget("user", "age");
      System.out.println(age);//20
    }

    @Test
    public void testZset() {
      Jedis jedis = new Jedis("127.0.0.1", 6379);
      jedis.zadd("program", 100, "java");
      jedis.zadd("program", 300, "php");
      jedis.zadd("program", 150, "mysql");
      Set<String> programs = jedis.zrange("program", 0, -1);
      System.out.println(programs);//
    }
}
案例:模拟发送手机验证码:


[*]输入手机号,点击发送后随机天生6位数字码,2 分钟有效
[*]输入验证码,点击验证,返回乐成或失败。
[*]每个手机号每天只能输入3次。I
https://img-blog.csdnimg.cn/direct/3d6a6e4ef7da47c3aa03173e7911bc92.png
package com.zhxd.test;

import redis.clients.jedis.Jedis;

import java.util.Random;
import java.util.Scanner;

public class TestVerfiCode {
    public static void main(String[] args) {
      System.out.println("请输入您的手机号:");
      Scanner scanner = new Scanner(System.in);
      String phoneNum = scanner.next();

      codeNormal(phoneNum);

      System.out.println("请输入六位验证码");
      String code = scanner.next();
      verfiCode(phoneNum, code);
    }
    //随机生成六位数的验证码
    public static String randomCode() {
      Random random = new Random();
      String code ="";
      for (int i = 0; i < 6; i++) {
            int rand = random.nextInt(9);
            code += rand;
      }
      return code;
    }

    //设置验证码规则
    public static void codeNormal(String phoneNum) {
      Jedis jedis = new Jedis("127.0.0.1", 6379);

      //设置每个手机每天只能发送3次验证码
      String phoneCountKey = phoneNum + ":count";
      String count = jedis.get(phoneCountKey);
      if(count == null) {
            jedis.setex(phoneCountKey, 24*60*60, "1");
      }else if(Integer.parseInt(count) <= 2) {
            jedis.incr(phoneCountKey);
      }else if(Integer.parseInt(count) >=3) {
            System.out.println("您的手机号今天已经发送三次验证码,不能再进行验证码发送");
            jedis.close();
            return;
      }

      //设置验证码在2分钟有效
      String codeKey = "CodeKey:" + phoneNum;
      String code = randomCode();
      System.out.println(code);
      jedis.setex(codeKey, 120, code);
    }

    //验证验证码
    public static void verfiCode(String phoneNum, String code) {
      Jedis jedis = new Jedis("127.0.0.1", 6379);
      String jcode = jedis.get("CodeKey:"+phoneNum);
      System.out.println(jcode);
      if(code.equals(jcode)) {
            System.out.println("登录成功");
      }else {
            System.out.println("验证码输入错误,请重新输入");
      }
    }
}
12.Redis事件

   Redis 事件是一个单独的隔离操纵:事件中的所有命令都会序列化、按顺序地实行。事件在实行的过程中,不会被其他客户端发送来的命令哀求所打断。Redis 事件的紧张作用就是串联多个命令防止别的命令插队。
12.1Multi、Exec、discard

   Redis 事件中有 Multi、Exec 和 discard 三个指令,在 Redis 中,从输入 Multi 命令开始,输入的命令都会依次进入命令队列中,但不会实行,直到输入 Exec 后,Redis 会将之前的命令队列中的命令依次实行。而组队的过程中可以通过 discard 来放弃组队。
https://img-blog.csdnimg.cn/direct/9d1f9e0443444cefa4667a1e74600dee.png


[*]案例:
https://img-blog.csdnimg.cn/direct/33a5752887ce4f10a55790c82d133d3f.png
组队乐成,乐成提交
https://img-blog.csdnimg.cn/direct/378ebef438d042f7a2322f9314d01835.png
放弃组队
12.2事件的错误处理


[*]组队中某个命令出现了报告错误,实行时整个的所有队列都会被取消
https://img-blog.csdnimg.cn/direct/3c6710aafa764f92a8700b84985008fc.png
[*]如果实行阶段某个命令报出了错误,则只有报错的命令不会被实行,而其他的命令都会实行,不会回滚
https://img-blog.csdnimg.cn/direct/f6eefb2e005442938f491b8b147fe09f.png
12.3事件辩论的题目



[*] 一个哀求想给金额减 8000
[*] 一个哀求想给金额减 5000
[*] 一个哀求想给金额减 1000
终极我们可以发现,统共金额是 10000,如果请责备部实行,那末了的金额变为 - 4000,很显着不合理
https://img-blog.csdnimg.cn/direct/85f5ae6a31ce46418ed35b46ea725e48.png
https://img-blog.csdnimg.cn/direct/bc2cc508aecb4db8af86f96a6a9b32b4.png
[*] 灰心锁:灰心锁 (Pessimistic Lock),顾名思义,就是很灰心,每次去拿数据的时候都以为别人会修改,以是每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操纵之前先上锁。
https://img-blog.csdnimg.cn/direct/1efb0f4ade604e4586dd13114771f933.png
[*] 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都以为别人不会修改,以是不会上锁,但是在更新的时候会判定一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁实用于多读的应用范例,这样可以进步吞吐量。Redis 就是使用这种 check-and-set 机制实现事件的。
https://img-blog.csdnimg.cn/direct/b872cb3738ba4d58b4b27c26f9d2ba9e.png
[*] WATCH key :在实行 multi 之前,先实行 watch key1 ,可以监视一个 (或多个) key ,如果在事件实行之前这个 (或这些) key 被其他命令所改动,那么事件将被打断
https://img-blog.csdnimg.cn/direct/1791ac491d704945b4914f2cd18da31f.png
unwatch:取消 WATCH 命令对所有 key 的监视。如果在实行 WATCH 命令之后,EXEC 命令或 DISCARD 命令先被实行了的话,那么就不需要再实行 UNWATCH 了。
[*] redis事件的三大特性:

[*]单独的隔离操纵 :事件中的所有命令都会序列化、按顺序地实行。事件在实行的过程中,不会被其他客户端发送来的命令哀求所打断。
[*]没有隔离级别的概念 :队列中的命令没有提交之前都不会现实被实行,因为事件提交前任何指令都不会被现实实行。
[*]不包管原子性 :事件中如果有一条命令实行失败,厥后的命令仍旧会被实行,没有回滚 。
12.4商品秒杀案例



[*]关键代码:
package com.zhxd.test;

import redis.clients.jedis.Jedis;

public class TestMS {
    public static boolean doSecKill(String uid, String prodid) {
      //1. 用户id和商品库存id非空判断
      if (uid == null || prodid == null) return false;

      //2. 连接redis
      Jedis jedis = new Jedis("127.0.0.1", 6379);

      //3. 拼接key
      //3.1库存key
      String kcKey = "sk:" + prodid + ":qt";
      //3.2秒杀成功的用户key
      String userKey = "sk:" + prodid + ":user";
      //4. 获取库存 ,如果库存null,秒杀还没开始
      if (jedis.get(kcKey) == null) {
            System.out.println("秒杀12:00开始,请稍候再试");
            jedis.close();
            return false;
      }

      // 5. 判断如果商品数量库存 < 1,则秒杀结束
      if (Integer.parseInt(jedis.get(kcKey)) < 1) {
            System.out.println("抱歉,商品已被抢光咯~");
            jedis.close();
            return false;
      }

      // 6. 判断用户是否重复秒杀
      if(jedis.sismember(userKey, uid)) {
            System.out.println("不能重复秒杀");
            jedis.close();
            return false;
      }

      // 7. 秒杀过程
      // 7.1 库存-1
      jedis.decr(kcKey);
      // 7.2 把秒杀成功用户添加到清单里面
      jedis.sadd(userKey, uid);
      System.out.println("恭喜!秒杀成功~");
      jedis.close();
      return true;
    }
}
上述代码在并发的条件下会发生超时和超卖的题目

[*]解决超时题目,使用数据库连接池:


[*]编写jedis数据库连接池工具类
public class JedisPoolUtil {
    private static volatile JedisPool jedisPool = null;

    public static JedisPool getJedisPool() {
      if(jedisPool == null) {
            synchronized (JedisPoolUtil.class) {
                JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
                jedisPoolConfig.setMaxTotal(-1);//制一个 pool 可分配多少个 jedis 实例,通过 pool.getResource () 来获取;如果赋值为 - 1,则表示不限制;如果 pool 已经分配了 MaxTotal 个 jedis 实例,则此时 pool 的状态为 exhausted。
                jedisPoolConfig.setMaxIdle(32);//控制一个 pool 最多有多少个状态为 idle (空闲) 的 jedis 实例
                jedisPoolConfig.setMaxWaitMillis(10*1000);//表示当 borrow 一个 jedis 实例时,最大的等待毫秒数,如果超过等待时间,则直接抛 JedisConnectionException;
                jedisPoolConfig.setBlockWhenExhausted(true);
                jedisPoolConfig.setTestOnBorrow(true);//获得一个 jedis 实例的时候是否检查连接可用性(ping ());如果为 true,则得到的 jedis 实例均是可用的。
                jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
            }
      }
      return jedisPool;
    }
}


[*]修改jedis实例的获取
//通过连接池获得jedis实例
JedisPool jedisPool = JedisPoolUtil.getJedisPool();
Jedis jedis = jedisPool.getResource();

[*]使用乐观锁解决超卖的题目
// 7. 秒杀过程
Transaction multi = jedis.multi();

//组队操作
multi.decr(kcKey);
multi.sadd(userKey, uid);

//执行
List<Object> results = multi.exec();

if (results == null || results.size() == 0) {
    System.out.println("sorry,秒杀失败了,请重新尝试噢~");
    jedis.close();
    return false;
}
System.out.println("恭喜!秒杀成功~");
jedis.close();
return true;
13.数据持久化

Redis 提供了 2 个差别形式的持久化方式:


[*]RDB(Redis DataBase)
[*]AOF(Append Of File)

[*]RDB模式
   默认方式,不需要进行配置,默认就使用这种机制,在一定的间隔时间中,检测key的厘革情况,然后持久化数据
编辑redis配置文件
https://img-blog.csdnimg.cn/direct/c81eed04cbe34a688cf03cc3604be0aa.png
会自动天生dump.rdb,发生宕机后,重新启动将会自动从备份文件中加载数据

[*]AOF模式
   可以在 redis.conf 中配置文件名称默以为 appendonly.aof 文件中开启,AOF 文件的保存路径,同 RDB 的路径一致。AOF 和 RDB 同时开启,系统默认取 AOF 的数据(数据不会存在丢失)。AOF 缓冲区根据 AOF 持久化计谋 将操纵 sync 同步到磁盘的 AOF 文件中,Redis 服务重启时,会重新 load 加载 AOF 文件中的写操纵到达数据恢复的目的。
https://img-blog.csdnimg.cn/direct/7124d162478d49cdb590d451698db1a6.png


[*]AOF 同步频率设置

[*]appendfsync always:始终同步,每次 Redis 的写入都会立刻记入日志;性能较差但数据完备性比较好。
[*]. appendfsync everysec:每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
[*]appendfsync no:redis 不自动进行同步,把同步机遇交给操纵系统。
https://img-blog.csdnimg.cn/direct/359247b78b204569845e56c9c6360117.png

14.redis主从复制

   主机数据更新后根据配置和计谋, 自动同步到备机的 master/slaver 机制,Master 以写为主,Slave 以`读``为主,主从复制节点间数据是全量的。
作用:


[*]读写分离,性能扩展
[*]容灾快速恢复
https://img-blog.csdnimg.cn/direct/7f568efefaa74fab8392d3c8a7dfa9f0.png
[*]配置一主两从

[*]复制两份配置文件
[*]修改配置文件的端口号,把6379改为6380,6381等
[*]使用三个配置文件启动三个redis服务(redis-server redis6379.conf redis-server redis6380.conf redis-server redis6381.conf)
[*]使用redis-cli -h 主机号 -p 端口号连接三个redis服务
[*]配置主从关系
https://img-blog.csdnimg.cn/direct/6d4616f2220d450bb42e8ebcdc5e1da9.png https://img-blog.csdnimg.cn/direct/28819f0c67214568bf0b354f1ec5ef8a.png
[*]检察主从关系(info replication)
https://img-blog.csdnimg.cn/direct/a2fc80fb25614c41bde4579361d56557.png
[*]主机宕机后,重新启动依然是主机
[*]从机宕机后,重新启动脚色是主机,需要重新配置主从关系,配置后,会同步主机数据
[*]主机宕机后,从机可以实行slaveof no one上位成为主机

14.1哨兵模式

   反客为主:当一个 master 宕机后,后面的 slave 可以立刻升为 master,厥后面的 slave 不消做任何修改。用 slaveof no one 指令将从机变为主机。而哨兵模式是反客为主的自动版,可以或许背景监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
https://img-blog.csdnimg.cn/direct/1676d5114da04e9b84fb83aec9ea3e68.png
哨兵配置:


[*]配置好主从关系
[*]配置好哨兵服务器的配置文件,只需要一句话sentinel monitor mymaster(主机名字,随意起一个) 127.0.0.1 6379 1(优先级)
[*]启动主机以及从机
[*]使用redis-sentinel 哨兵配置文件(sentinel.conf)启动哨兵服务器
主机宕机后重新启动会成为从机,而不会重新成为主机
15.redis集群

   Redis 集群(包罗很多小集群)实现了对 Redis 的水平扩容,即启动 N 个 redis 节点,将整个数据库分布存储在这 N 个节点中,每个节点存储总数据的 1/N,即一个小集群存储 1/N 的数据,每个小集群里面维护好本身的 1/N 的数据。Redis 集群通过分区(partition)来提供一定水平的可用性(availability): 即使集群中有一部门节点失效或者无法进行通讯, 集群也可以继续处理命令哀求。该模式的 redis 集群特点是:分治、分片。
15.1 redis搭建集群(模拟搭建)


[*]创建一个三主三从的集群服务器,在linux创建6个redis配置文件,端口号分别是:6379、6380、6381、6389、6390、6391
include /temp/myredis/redis.conf
port 6379
pidfile "/var/run/redis_6379.pid"
dbfilename "dump6379.rdb"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
daemonize yes

[*]开启六个redis服务
[*]组合六个redis服务,需要进入到redis安装包目录
redis-cli --cluster create --cluster-replicas 1 192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391


[*]此处不要使用127.0.0.1,请使用真实的ip地址
[*]--replicas 1:采用最简单的方式配置集群,一台主机,一台从机,正好三组

[*]使用redis-cli -c -p 端口号连接redis服务器
[*]cluster nodes检察集群信息
https://img-blog.csdnimg.cn/direct/84699622b8b54b3b97b1ba21aa779fe5.png


[*]redis cluster 如何分配这六个节点?

[*]一个集群至少要有三个主节点
[*]选项 –cluster-replicas 1 :表示我们希望为集群中的每个主节点创建一个从节点
[*]配原则只管包管每个主数据库运行在差别的 IP 地址,每个从库和主库不在一个 IP 地址上

15.2什么是 slots

   一个 Redis 集群包含 16384 个插槽(hash slot),数据库中的每个键都属于这 16384 个插槽的其中一个。集群使用公式 CRC16 (key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16 (key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部门插槽。 举个例子, 如果一个集群可以有主节点, 其中:节点 A 负责处理 0 号至 5460 号插槽,节点 A 负责处理 0 号至 5460 号插槽,节点 C 负责处理 10923 号至 16383 号插槽。
https://img-blog.csdnimg.cn/direct/7ed89ef9830444d29a3adc6525911635.png


[*]插入单个值:
https://img-blog.csdnimg.cn/direct/e543bf0928e34fc9b56969f2a6e5597a.png
[*]插入多个值
https://img-blog.csdnimg.cn/direct/74758a9b7d8b4ae891dfb3c3d3fa2bef.png
集群对用的命令:

[*]cluster keyslot :计算当前key属于哪个插槽
[*]cluster countkeysinslot [插槽值]:计算当前插槽有多少个key
15.3 故障恢复



[*]如果主节点下线?从节点能否自动升为主节点?留意:15 秒超时
[*]主节点恢复后,主从关系会如何?主节点回来变成从机
[*]如果所有某一段插槽的主从节点都宕掉,redis 服务是否还能继续?

[*]如果某一段插槽的主从都挂掉,而 cluster-require-full-coverage 为 yes ,那么整个集群都挂掉
[*]如果某一段插槽的主从都挂掉,而 cluster-require-full-coverage 为 no ,那么,该插槽数据全都不能使用,也无法存储

15.4 jedis操纵redis集群

package com.zhxd.test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class TestJedisCluster {
    public static void main(String[] args) {
      //添加主机以及端口号
      HostAndPort hostAndPort = new HostAndPort("168.192.0.122", 6379);
      //创建jedis集群对象
      JedisCluster jedisCluster = new JedisCluster(hostAndPort);
      //操作
      jedisCluster.set("k1", "111");
      System.out.println(jedisCluster.get("k1"));
      //关闭资源
      jedisCluster.close();
    }
}
15.5 redis集群优缺点


[*]优点:


[*]实现扩容
[*]分摊压力
[*]无中心配置相对简单

[*]缺点:


[*]多键操纵是不被支持的
[*]多键的 Redis 事件是不被支持的,lua 脚本不被支持
[*]由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至 redis cluster,需要整体迁移而不是渐渐过渡,复杂度较大

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: redis