Redis分布式入门

本文是Java企业级电商项目学习笔记,介绍Redis分布式算法原理,如一致性hash算法及哈希倾斜问题与解决办法;阐述Redis分布式环境配置,将Windows中Redis分成两个文件夹并启动;还讲解Springboot2.13操作分布式Redis,包括配置参数、创建连接池及插入数据等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:本文章为慕课网上Java企业级电商项目架构演进之路Tomcat集群与Redis分布式的学习笔记.

目录

第一章 Redis分布式算法原理

 1.1 一致性hash算法(Consistent hashing)

1.2 哈希倾斜

第二章 Redis分布式环境配置

2.1 配置两个redis

第三章 Springboot2.13操作分布式redis

3.1 配置redis参数

3.2 创建redis的连接池

3.3 操作redis


第一章 Redis分布式算法原理

当我们有20个数据,4个redis结点时,我可以按照取模的方法,对这20个数据进行一一分配.即1%4=1,所以1数据分配到1节点上,4%4=0所以4分配到0节点上,分配完后如下图所示.

当我们想按如上规则增加一个redis节点时,我们发现只有四个节点的位置不需要重新分配,这样命中率只有4/20=20%,即百分之20的节点不需要重新分配.这样效率有点低,我们需要一个新的算法来分配数据节点,来保证新增或删除redis节点时,不需要有太多的数据节点被重新分配.

 1.1 一致性hash算法(Consistent hashing)

通常hash算法是将value映射到一个32位的key值当中,我们将数轴卷起变为收尾相接的圆环,取值范围位从0-2^32-1.也就是这个环能存储2^32-1个元素.

考虑四个对象object1~object4,通过hash函数计算出hash值key,,比如object1经过hash后的值称为key1,如下图,于是四个对象就都被映射到了哈希空间中.

我们的object需要cache来进行存储,所以我们要将object和cache都映射到同一个hash数值空间中,并且使用相同的hash算法,对于cache的哈希计算,可以使用机器的ip,机器名作为hash的输入,也可以引入更多的因子,如端口号.

假设我们有三个cache,映射后就如下图所示.

如何把对象映射到cache中呢?沿着key所在的位置顺时针出发所碰到的第一个cache节点是CacheA,那么key1(简称1)就要存到CacheA(简称A)中,这样就找到了对象映射到缓存中的方案.都映射完如下图所示.

我们的生产环境可能会调整,传统的取模方式对后台服务器造成了巨大的冲击,我们现在移除Cache节点,移除CacheB,object4就会按照原来的算法找到CacheC,存到Cache C中.

所以移除CacheB后影响的范围就是橙色框中的节点. 

增加CacheD后影响的就是橙色框中的节点.

1.2 哈希倾斜

根据上面的论述,Cache节点的位置影响着重新分配数据时的效率,我们理想的Cache节点分布如下图.

现实可能是这样的.如果时这样大量的数据就会落到A上面,导致A很忙,B,C很倾斜.同时去掉A时也会影响大量节点.

为了解决这个问题,引入了虚拟节点.我们先将我们的数据映射到分布均匀的虚拟节点上,再将虚拟节点映射到真正的Cache节点上.

我们增加虚拟节点A,B,C,加完后如下图,这样1,3落在A上,2,6落在C上,5,4落在B上.可是这样虚拟节点也会有哈希倾斜性,我们可以增加大量的虚拟节点,给虚拟节点分配一个良好的比例,随着节点越来越多,数据越来越多,增加和删除节点的影响就会降到最低.

命中率计算公式,服务器台数是n,新增的服务器台数是m

(1-n/(n+m))*100%

之前用取模的方式命中率只有20%,虽然都是百分之20,但是那是因为数据量很小,当我们扩大到百万级,我们变动的服务器台数越大,命中率就会越高,所以这个算法是说随着我们的分布式集群越来越大的时候,这个算法的优点就会体现出来.Consistant已经最大限制的抑制了哈希的重新分布,而且我们还可以运用虚拟节点的思想,让每个实际节点都配置个100-500个虚拟节点,这样就能抑制分布不均匀了.

第二章 Redis分布式环境配置

2.1 配置两个redis

我们将windows中的redis分成两个文件夹

第一个直接启动

第二个修改配置文件端口为6380然后启动

 

第三章 Springboot2.13操作分布式redis

3.1 配置redis参数

两个redis都是架在本地的所以地址都是127.0.0.1,一个端口是6379,一个端口是6380.

redis2.maxtotal = 20
redis2.maxIdle = 10
redis2.minIdle = 2
redis2.testOnReturn = true
redis2.testOnBorrow = true
redis2.redisPort1 = 6379
redis2.redisIp1 = 127.0.0.1
redis2.redisPort2 = 6380
redis2.redisIp2 = 127.0.0.1

3.2 创建redis的连接池

@Component
@ConfigurationProperties(prefix = "redis2")
@Slf4j
@Getter
@Setter
public class RedisShardedPool {
    private ShardedJedisPool pool;//jedis连接池
    private Integer maxtotal  ; //最大连接数
    private Integer maxIdle ; //在jedispool中最大的idle(空闲的)状态的jedis实例的个数
    private Integer minIdle ; //在jedispool中最小的idle(空闲的)状态的jedis实例的个数
    private Boolean testOnBorrow ;
    private Boolean testOnReturn ;
    private Integer redisPort1 ;
    private String redisIp1;
    private Integer redisPort2 ;
    private String redisIp2;
    public RedisShardedPool(){
        log.info("构造方法开始执行");
    }
    @PostConstruct
    public void initPool(){
         log.info("属性已经注入");
        log.info("开始创建连接池");
        JedisPoolConfig config = new JedisPoolConfig();

        config.setMaxTotal(maxtotal);
        config.setMaxIdle(maxIdle);
        config.setMinIdle(minIdle);

        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);

        config.setBlockWhenExhausted(true);

        JedisShardInfo info1 = new JedisShardInfo(redisIp1,redisPort1,1000*2);
        JedisShardInfo info2 = new JedisShardInfo(redisIp2,redisPort2,1000*2);

        List<JedisShardInfo> jedisShardInfoList = new ArrayList<JedisShardInfo>(2);
        jedisShardInfoList.add(info1);
        jedisShardInfoList.add(info2);
        //Hashing.MURMUR_HASH是分篇策略,应用的是一致性分布算法.
        pool= new ShardedJedisPool(config,jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
    }
    public ShardedJedis getJedis(){
        return pool.getResource();
    }
}

3.3 操作redis

我们向redis中插入了10个值

@RequestMapping("/testSharedJedis")
    public String testSharedJedis(){
        ShardedJedis shardedJedis = redisShardedPool.getJedis();
        for(int i=0;i<10;i++){
            shardedJedis.set("hey"+i,"value"+i);
        }
        return "index";
    }

分别查看两个redis库中的值

接口为6379的数据库:

接口为6380的数据库:

可以看到已经向两个数据库中插入了值,操作成功!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值