分享redis基础知识(八)

54 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第32天,点击查看活动详情

image.png redis cluster集群

优点:master去中心化,数据通过卡槽分摊,动态实现扩容和缩容。

如果有3个主节点的情况下,新增一个主节点

16384/4=4096,其他3个节点均会分出4096/3个卡槽给第四个主节点(也可以指定某个节点分配多少个卡槽),对应的数据也会一块迁移到新的主节点

image.png 新增的节点去读之前的dump.rdb文件,dump.rbd修改文件名称,每个节点读不同的rdb文件,防止扩容时,出现键冲突

\

\

扩容:

/usr/redis/bin/redis-server /usr/rediscluster/redis7006/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7007/redis.conf

/usr/redis/bin/redis-cli -h 192.168.212.163 -p 7000

新增一个主节点 为7006

/usr/redis/bin/redis-cli --cluster add-node 192.168.212.163:7006   192.168.212.163:7000

新增一个从节点 为7007

/usr/redis/bin/redis-cli --cluster add-node 192.168.212.163:7007   192.168.212.163:7000  --cluster-salve  --cluster-master-id       5d94171eb34ed4396bf5b9db8efaab4d96d0cf10

5d94171eb34ed4396bf5b9db8efaab4d96d0cf10就是cluster nodes命令下的每个节点的id,指定master的id

新增的7006 是没有任何槽位

分配Redis槽位扩容

cluster slots

/usr/redis/bin/redis-cli --cluster reshard  192.168.212.163:7000

指定多少卡槽

以什么方式all/done,all节点平均分,done节点指定分

缩容:

/usr/redis/bin/redis-cli --cluster  reshard  192.168.212.163:7000  --cluster-from   5d94171eb34ed4396bf5b9db8efaab4d96d0cf10  --cluster-to 511058958a3b80dd600e060c2500050c6c5a02ab  --cluster-slots

5d94171eb34ed4396bf5b9db8efaab4d96d0cf10  缩容的节点id

511058958a3b80dd600e060c2500050c6c5a02ab  把缩容的卡槽给哪个节点

jedis(java的客户端连接工具,单机,不支持集群)

首先jedis加全部的节点,放入到连接池中,配置连接池到jedisCluster中,去对reids操作。

原理根据key算出对应的hash槽,然后help查出节点对应的槽,然后连接到哪个节点,所以直接连接一个节点就可以了,在底层实现了转发。

布隆过滤器解决缓存穿透问题

布隆过滤器:

高效的判断一个元素在集合中是否存在,但是可能存在误判问题(出现极低)

实现的原理采用二进制向量数组和随机映射hash函数

一个值会有3个hash值,存放到布隆过滤其中,如果3个都为1,则都会判定为存在这个值。

0代表没有hash值

1代表存在hash值

meite出现误判问题,计算的hash与其他元素的hash出现重叠。

解决方法:二进制数组长度设置长一点。

如果特别严谨,不能使用布隆过滤器,只能用于不严谨的功能。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>22.0</version>
</dependency>
public class BlongTest {
    /**
     * 在布隆中存放100万条数据
     */
    private static Integer size = 1000000;

    public static void main(String[] args) {
        BloomFilter<Integer> integerBloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.01);
        for (int i = 0; i < size; i++) {
            integerBloomFilter.put(i);
        }
        // 从布隆中查询数据是否存在
        ArrayList<Integer> strings = new ArrayList<>();
        for (int j = size; j < size + 10000; j++) {
            if (integerBloomFilter.mightContain(j)) {
                strings.add(j);
            }
        }
        System.out.println("误判数量:" + strings.size());
        //0.01误判概率变小
        //0.03误判概率变大
        //0.001误判概率变特别小

    }
}
@RequestMapping("/getOrder")
  public OrderEntity getOrder(Integer orderId) {
    if (integerBloomFilter != null) {
        if (!integerBloomFilter.mightContain(orderId)) {
            System.out.println("从布隆过滤器中检测到该key不存在");
            return null;
        }
    }

  
    // 1.先查询Redis中数据是否存在
    OrderEntity orderRedisEntity = (OrderEntity) redisTemplateUtils.getObject(orderId + "");
    if (orderRedisEntity != null) {
        System.out.println("直接从Redis中返回数据");
        return orderRedisEntity;
    }
    // 2. 查询数据库的内容
    System.out.println("从DB查询数据");
    OrderEntity orderDBEntity = orderMapper.getOrderById(orderId);
    if (orderDBEntity != null) {
        System.out.println("将Db数据放入到Redis中");
        redisTemplateUtils.setObject(orderId + "", orderDBEntity);
    }
    return orderDBEntity;
}

//布隆过滤器预热
  @RequestMapping("/dbToBulong")
  public String dbToBulong() {
    List<Integer> orderIds = orderMapper.getOrderIds();
    integerBloomFilter = BloomFilter.create(Funnels.integerFunnel(), orderIds.size(), 0.01);
    for (int i = 0; i < orderIds.size(); i++) {
        integerBloomFilter.put(orderIds.get(i));
    }
    return "success";
}