redis的分布式原理及连接池

 

redis的分布式结构

数据分片

将计算后的数据分成的不同部分,存储在不同的数据节点中叫做数据分片

hash取余的自定义算法实现分布式

hash取余公式

(key.hashCode()&Integer.MAX_VALUE)%N

括号中的是正整数,N 是分片的节点个数

@Test
@Test
         public void test05(){
             //准备一下连接的所有节点jedis对象
             Jedis jedis1=new Jedis("10.9.39.13",6379);
             Jedis jedis2=new Jedis("10.9.39.13",6380);
             Jedis jedis3=new Jedis("10.9.39.13",6381);
             //模拟生成海量数据
             int count=0;
             for(int i=0;i<1000;i++){
                 String key=UUID.randomUUID().toString();
                 //利用hash取余算法,处理存储的分布式计算
                 //key是0/1/2的概率是多少
                 //获取算法的结果 0 1 2 
                 int n=(key.hashCode()&Integer.MAX_VALUE)%3;
                 if(n==0){
                     count++;
                     jedis1.set(key, "");
                 }else if(n==1){
                     jedis2.set(key, "");
                 }else{
                     jedis3.set(key, "");
                 }
             }
             System.out.println("是的概率:"+count/1000.0);
         }
 

 

 

jedis的分片对象

ShardedJedis

@Test
  @Test
         public void test06(){
             //使用jedis提供的分片计算对象实现分布式处理数据
             //收集节点信息,告诉jedis到底有多少个分片信息
             List<JedisShardInfo> info=new ArrayList<JedisShardInfo>();
             //将节点信息封装添加到info
             info.add(new JedisShardInfo("10.9.39.13", 6379));
             info.add(new JedisShardInfo("10.9.39.13", 6380));
             info.add(new JedisShardInfo("10.9.39.13", 6381));
             //利用节点信息对象info构造一个封装了分片算法的分片对象
             ShardedJedis sJedis=new ShardedJedis(info);
             //通过测试生成的任何key值都会进行分片计算
             sJedis.set("name", "王老师");
             System.out.println(sJedis.get("name"));
             System.out.println(sJedis.exists("name"));
         }
 

 

 

hash一致性计算原理(可搜索图解)

hash一致性,基于一个散列计算的数学计算方法实现

任何计算机中的对象都可以通过散列方法获取一个整数值,整数区间[0,2^32-1]

这个整数区间--hash环

节点映射关系

ip+port在内存中保存为一个字符串

这个字符串通过散列计算,在hash环上映射成一个整数值

key值的映射

先做key的整数映射

key值不变,结果整数同一个

数据分片计算方法

通过找到key值的对应节点关系,寻找key对应的节点

顺时针寻找最近的节点整数

数据平衡性(权重)

虚拟节点:

key顺时针寻找最近节点,对应到虚拟节点后,从虚拟节点和真实节点的关系找到真实节点

只要虚拟节点数量够多,平衡心越高

如何解决扩容迁移量过大的问题

==hash取余==,一种目前比较成熟的计算分片方法,但是在redis结构中不适合

因为造成redis集群扩容,缩容时数据迁移量过大的问题;

hash取余的计算方法造成扩容的迁移量过大,不迁移造成雪崩

==hash一致性算法==,从已有的映射关系环上添加新的节点,节点数量越多,弧线越短(key值量越少);

节点越多,做扩容,缩容时需要迁移的数据量就越少----少到一定程度是,就不需要迁移了

虚拟节点的个数,默认是160*weight,weight默认值时1

按照默认值计算分片 比重1:1:1

  • hash一致性的缺点

    数据倾斜

    key值的对应服务的强耦合

 

 

 

分片连接池

@test
        @Test
         public void test07(){
             //最底层连接池 Jedis
             JedisPool pool=new JedisPool("10.9.39.13", 6379);
             //pool 获取jedis对象
             Jedis jedis = pool.getResource();
             pool.returnResource(jedis);
             //分片连接池 基于jedisPool来创建的
             //收集节点信息,告诉jedis到底有多少个分片信息
             List<JedisShardInfo> info=new ArrayList<JedisShardInfo>();
             //将节点信息封装添加到info
             info.add(new JedisShardInfo("10.9.39.13", 6379, 1000, 1000, 5));
             info.add(new JedisShardInfo("10.9.39.13", 6380));
             info.add(new JedisShardInfo("10.9.39.13", 6381));
             //构造一个分片连接池需要一些配置信息,连接池的初始化连接数
             //最大空闲数,最小空闲数,连接池的连接上限
             GenericObjectPoolConfig config=
                     new GenericObjectPoolConfig();
             config.setMaxTotal(200);//最大连接数
             config.setMaxIdle(8);//最大空闲数
             config.setMinIdle(3);//最小空闲数
             //构造连接池
             ShardedJedisPool sPool=new 
                     ShardedJedisPool(config,info);
             ShardedJedis sJedis = sPool.getResource();
             sJedis.set("location", "北京");
             System.out.println(sJedis.get("location"));
             sPool.returnResource(sJedis);
         }

 

posted @ 2021-03-16 09:26  minnersun  阅读(444)  评论(0编辑  收藏  举报