redis

1.Redis简介

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

2.Redis的特点

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

3.redis的启动和关闭方式

  1. 开启
  • 前台启动:redis-server
    在这里插入图片描述
    关闭此窗口,redis服务关闭
  • 后台启动:redis-server &
  • 根据配置文件启动 启动命令 配置文件 &:redis-server & 配置文件
  1. 关闭
  • 任意目录下执行 指令redis-cli shutdown(推荐)
  • kill pid 或者 kill -9 pid

4.Key相关操作

命令 说明
keys * 查看当前库所有 key
exists 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,只能对数字值操作,如果为空,新增值为 1
decr key 将 key 中储存的数字值减 1,只能对数字值操作,如果为空,新增值为-1
incrby / decrby key step 将 key 将 key 中储存的数字值增减。自定义步长
get key 查询对应键值
mget k1 k2 k3… 同时获取一个或多个 value
getrange key 起始位置 结束位置 获得值的范围,类似 java 中的 substring,前包,后包
get key value 以新换旧,设置了新值同时获得旧值

6.redis列表(List)操作

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个双向链表,对两端的操作性能很高通过索引下标的操作中间的节点性能会较差

在这里插入图片描述

命令 说明
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键赋value
hget key field 从key1集合field取出 value
hmset key field1 valuel field2 value2 批量设置 hash 的值
hexists key field 査看哈希表 key 中,给定域 field 是否存在
hkeys key 列出该 hash 集合的所有 field
hvals key 列出该 hash 集合的所有 value
hincrby key field increment 为哈希表 key 中的域 field 的值加上增量 1 -1
hsetnx 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 [withscores] 返回有序集 key 中,下标在start stop之间的元素,带 WITHSCORES,可以让分数一起和值返回到结果集
zrangebyscore key min max [withscores] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员.有序集成员按 score 值递增(从小到大)次序排列
zrevrangebyscore key max min [withscores] 同上,改为从大到小排列
zincrby key increment value 为元素的 score 加上增量
zrem key value 删除该集合下,指定值的元素
zcount key min max 统计该集合,分数区间内的元素个数
zrank key value 返回该值在集合中的排名,从0开始

10.redis发布订阅

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

  1. 客户端订阅信息
    在这里插入图片描述
  2. 服务端发布消息
    在这里插入图片描述
  • redis订阅信息:SUBSCRIBE channe1 [channel2 channel2...]
    在这里插入图片描述
  • redis发布信息:publish channe message
    在这里插入图片描述

在这里插入图片描述

11.redis新增的数据类型

10.1Bitmaps

  • Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作
  • Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。
    在这里插入图片描述
  1. setbit key offset value设置Bitmaps中某个偏移量的值(0或1),offset从0开始
    在这里插入图片描述
  2. getbit key offset获取Bitmaps中某个偏移量的值
    在这里插入图片描述
  3. bitcount key [start end]统计字符串从 start 字节到 end 字节比特值为 1的数量
    在这里插入图片描述

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。 基数估计就是在误差可接受的范围内,快速计算基数。
  1. pfadd key element [element...]添加指定元系到 HyperLogLog 中
  2. pfcount key [key...]计算 HLL 的近似基数,可以计算多个 HLL,比如用 HLL 存储每天的 UV,计算一周的 UV 可以使用7天的 UV 合并计算即可
    在这里插入图片描述
  3. pfmerge destkey sourcekey [sourcekey...]将一个或多个 HLL 合并后的结果存储在另一个 HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得。
    在这里插入图片描述

10.3Geospatial

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

  1. geoadd key longitde latitude member添加地理位置(经度,纬度,名称)
    在这里插入图片描述
  2. geopos key member [member...]获得指定地区的坐标值
    在这里插入图片描述
  3. geodist key member1 member2 [m|km|ft|mi]获取两个位置之间的直线距离
  • m 表示单位为米[默认值]
  • km 表示单位为千米
  • mi 表示单位为英里
  • t 表示单位为英尺
    在这里插入图片描述
  1. georadius key longitude latiitude raduis m|km|ft|mi以给定的经纬度为中心找出某一半径内的元素
    在这里插入图片描述

11.Jedis

Jedis是使用java来操作redis数据库,与jdbc类似

java操作redis是使用Jedis对象进行操作的:
在这里插入图片描述
使用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);//[java, mysql, php]
    }
}

案例:模拟发送手机验证码:

  • 输入手机号,点击发送后随机生成6位数字码,2 分钟有效
  • 输入验证码,点击验证,返回成功或失败。
  • 每个手机号每天只能输入3次。I
    在这里插入图片描述
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 来放弃组队。

在这里插入图片描述

  • 案例:
    在这里插入图片描述
    组队成功,成功提交

在这里插入图片描述
放弃组队

12.2事务的错误处理

  1. 组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消
    在这里插入图片描述
  2. 如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚
    在这里插入图片描述

12.3事务冲突的问题

  • 一个请求想给金额减 8000

  • 一个请求想给金额减 5000

  • 一个请求想给金额减 1000
    最终我们可以发现,总共金额是 10000,如果请求全部执行,那最后的金额变为 - 4000,很明显不合理
    在这里插入图片描述
    在这里插入图片描述

  • 悲观锁:悲观锁 (Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
    在这里插入图片描述

  • 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis 就是利用这种 check-and-set 机制实现事务的。
    在这里插入图片描述

  • WATCH key [key …]:在执行 multi 之前,先执行 watch key1 [key2],可以监视一个 (或多个) key ,如果在事务执行之前这个 (或这些) key 被其他命令所改动,那么事务将被打断
    在这里插入图片描述
    unwatch:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后,EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了。

  • redis事务的三大特性:

  1. 单独的隔离操作 :事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  2. 没有隔离级别的概念 :队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行。
  3. 不保证原子性 :事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚 。

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;
    }
}

上述代码在并发的条件下会发生超时和超卖的问题

  1. 解决超时问题,使用数据库连接池:
  • 编写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();
  1. 使用乐观锁解决超卖的问题
// 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)
  1. RDB模式

默认方式,不需要进行配置,默认就使用这种机制,在一定的间隔时间中,检测key的变化情况,然后持久化数据

编辑redis配置文件
在这里插入图片描述
会自动生成dump.rdb,发生宕机后,重新启动将会自动从备份文件中加载数据

  1. AOF模式

可以在 redis.conf 中配置文件名称默认为 appendonly.aof 文件中开启,AOF 文件的保存路径,同 RDB 的路径一致。AOF 和 RDB 同时开启,系统默认取 AOF 的数据(数据不会存在丢失)。AOF 缓冲区根据 AOF 持久化策略 [always,everysec,no] 将操作 sync 同步到磁盘的 AOF 文件中,Redis 服务重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的。

在这里插入图片描述

  • AOF 同步频率设置
    • appendfsync always:始终同步,每次 Redis 的写入都会立刻记入日志;性能较差但数据完整性比较好。
    • . appendfsync everysec:每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
    • appendfsync no:redis 不主动进行同步,把同步时机交给操作系统。
      在这里插入图片描述

14.redis主从复制

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

作用:

  • 读写分离,性能扩展
  • 容灾快速恢复
    在这里插入图片描述
  • 配置一主两从
    • 复制两份配置文件
    • 修改配置文件的端口号,把6379改为6380,6381等
    • 使用三个配置文件启动三个redis服务(redis-server redis6379.conf redis-server redis6380.conf redis-server redis6381.conf
    • 使用redis-cli -h 主机号 -p 端口号连接三个redis服务
    • 配置主从关系
      在这里插入图片描述 在这里插入图片描述
    • 查看主从关系(info replication
      在这里插入图片描述
    • 主机宕机后,重新启动依然是主机
    • 从机宕机后,重新启动角色是主机,需要重新配置主从关系,配置后,会同步主机数据
    • 主机宕机后,从机可以执行slaveof no one上位成为主机

14.1哨兵模式

反客为主:当一个 master 宕机后,后面的 slave 可以立刻升为 master,其后面的 slave 不用做任何修改。用 slaveof no one 指令将从机变为主机。而哨兵模式是反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。

在这里插入图片描述
哨兵配置:

  • 配置好主从关系
  • 配置好哨兵服务器的配置文件,只需要一句话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搭建集群(模拟搭建)

  1. 创建一个三主三从的集群服务器,在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
  1. 开启六个redis服务
  2. 组合六个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:采用最简单的方式配置集群,一台主机,一台从机,正好三组
  1. 使用redis-cli -c -p 端口号连接redis服务器
  2. cluster nodes查看集群信息
    在这里插入图片描述
  • 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 号插槽。

在这里插入图片描述

  • 插入单个值:
    在这里插入图片描述
  • 插入多个值
    在这里插入图片描述
    集群对用的命令:
  1. cluster keyslot [key]:计算当前key属于哪个插槽
  2. 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集群优缺点

  1. 优点:
  • 实现扩容
  • 分摊压力
  • 无中心配置相对简单
  1. 缺点:
  • 多键操作是不被支持的
  • 多键的 Redis 事务是不被支持的,lua 脚本不被支持
  • 由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至 redis cluster,需要整体迁移而不是逐步过渡,复杂度较大

相关推荐

  1. <span style='color:red;'>Redis</span>

    Redis

    2024-06-07 10:04:03      38 阅读
  2. <span style='color:red;'>Redis</span>

    Redis

    2024-06-07 10:04:03      54 阅读
  3. <span style='color:red;'>Redis</span>

    Redis

    2024-06-07 10:04:03      28 阅读
  4. <span style='color:red;'>redis</span>

    redis

    2024-06-07 10:04:03      45 阅读
  5. <span style='color:red;'>Redis</span>

    Redis

    2024-06-07 10:04:03      37 阅读
  6. <span style='color:red;'>redis</span>

    redis

    2024-06-07 10:04:03      43 阅读
  7. <span style='color:red;'>Redis</span>

    Redis

    2024-06-07 10:04:03      41 阅读
  8. <span style='color:red;'>redis</span>

    redis

    2024-06-07 10:04:03      42 阅读
  9. Redis

    2024-06-07 10:04:03       36 阅读
  10. <span style='color:red;'>redis</span>

    redis

    2024-06-07 10:04:03      41 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-07 10:04:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-07 10:04:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-07 10:04:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-07 10:04:03       18 阅读

热门阅读

  1. 【Redis】Redis事务详解

    2024-06-07 10:04:03       7 阅读
  2. 存储器的层次结构

    2024-06-07 10:04:03       7 阅读
  3. AI学习指南机器学习篇-决策树算法简介

    2024-06-07 10:04:03       8 阅读
  4. 2020年09月C语言二级真题

    2024-06-07 10:04:03       10 阅读
  5. 用Pip配置Pytorch环境 (Pytorch==2.3.0)

    2024-06-07 10:04:03       9 阅读
  6. oracle服务器存储过程中调用http

    2024-06-07 10:04:03       6 阅读