站内导航

Redis分布式缓存设计与实现
原创文章,转载请注明出处
概述

随着系统负载原来越大,单台reids已无法满足系统负载、安全等要求。本设计目标在于加大Redis服务吞吐量,支持动态扩展reids集群,支持自定义每台reids服务器负载、支持宕机请求自动转移。


1. 集群配置

集群通过xml文件配置,在系统初始化时,根据配置的集群数量动态生成对应大小的redis连接池数组pools[n]。根据配置顺序,第一个服务器对应的连接池为pools[0]

注意:pools[0]为默认连接池,如自增计数器等可指定存储至0号机器。

 <redisPoolConfig>

        <!-- 0台:存储购物车等不能清空的数据,不参加散列 -->

      <redis>

           <redisIp>xx.xx.xx.xxx</redisIp>

           <redisPort>6379</redisPort>

      </redis>

      <!-- 1台:mget等批量获取,不能分散存储的数据,不参加散列 -->

      <redis>

           <redisIp> xx.xx.xx.xxx</redisIp>

           <redisPort>6379</redisPort>

      </redis>

      <!-- 散列存储数据机器 第2台至n-->

      <redis>

           <redisIp> xx.xx.xx.xxx</redisIp>

           <redisPort>6379</redisPort>

      </redis>

      <redis>

           <redisIp> xx.xx.xx.xxx</redisIp>

           <redisPort>6379</redisPort>

      </redis>

      </redisPoolConfig>


2.负载均衡配置

由于各机器性能等不一致,因此需要支持根据机器性能配置redis服务器负载,1<index<redis服务器数量(第0台存储购物车等不能清空的数据,第一台存储不能分散存储的数据,第0台、第1台不参与散列)。配置如下:

<redisPoolLoad>

        <!-- index=n 表示映射至 redisPoolConfig中第n-1个服务器,1<n<redis数量(第0,1台不参与散列) -->

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      <redis index="2"></redis>

      <redis index="3"></redis>

      </redisPoolLoad>

注意:1<n<reids服务器数量

根据上面的配置文件动态生成一个大小为k的映射数组,mapped[k]kredisLoad中的子节点数)。mapped[3]=1,表示当hashcode=3时(hashcode由待存储数据的主键计算而来,详情见【Redis选择】),对应数据存储至1redis服务器。

 

3.Redis选择

private static Jedis getRedis(String key) {

      int hashcode = Math.abs(key.hashCode()%K);//kredis映射数组mapped的大小

      int redisIndex = mapped[hashcode]; //mappedredis映射数组

      return pool[redisIndex].getResource();

}

注:其它特殊要求的可直接存储至0号默认机器(如:存储的key为二进制,未登录用户的购物车数据,自增计数器)


4.Redis节点宕机处理

当发现有reids宕机时,可将该hashcode+1,映射至其它节点,代码如下: hashcode = Math.abs(  (key.hashCode()+1)   %K);

由于根据hashcode得出的映射为虚拟节点,同一台redis有多个虚拟节点,因此宕机的reids数据可以分散至其它redis服务器,不会出现雪崩情况(mapped虚拟节点越多,redis负载越均衡)


5.特殊数据不参加散列处理

在系统设计中,可能有特殊数据不能随机散列,如:未登录用户购物车数据(该数据不能随意删除)、批量数据(使用mget批量获取的数据)等。

解决方案:不能散列的数据的key以特殊字符串开头,如:redis0_ ,redis1_ 。reids0_开头的数据直接存储在0号机器,不参与散列。


©crap.cn  本系统由CrapApi开源项目生成