持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第32天,点击查看活动详情
redis cluster集群
优点:master去中心化,数据通过卡槽分摊,动态实现扩容和缩容。
如果有3个主节点的情况下,新增一个主节点
16384/4=4096,其他3个节点均会分出4096/3个卡槽给第四个主节点(也可以指定某个节点分配多少个卡槽),对应的数据也会一块迁移到新的主节点
新增的节点去读之前的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";
}