Redis 客戶端分片模式

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

0x01:分區的概念

  分區就是將數據分割到多個Redis實例,所以每一個實例只保存一部分key - value,每個 Redis 實例的 key 的一個子集。node

  若是隻使用一個 Redis 實例時,那麼這個 Redis 實例保存了服務器中所有的緩存數據,這樣會有很大風險,若是單臺 Redis 服務宕機了將會影響到整個服務。解決方案能夠採用分片 / 分區的技術,將原來一臺服務器維護的整個緩存,換爲由多臺服務器共同維護內存空間。redis

 

0x02: 分片的實現

  採用在一臺主機上實現分片的方式,因此只須要在該主機上配置啓動三臺 Redis 的實例。由於 Redis 默認使用的端口號爲6379,因此這裏分別使用637九、6380以及6381三個端口來實現。算法

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

配置:

一、進入到 Redis 的安裝目錄下,建立一個 shard 文件夾,而後將 Redis 的配置文件 redis.conf 複製一份,取名爲redis-6379.conf ( 做爲6379這臺實例的配置文件 )。而後將該文件移動到shard文件夾下,再將 redis-6379.conf 複製兩份。緩存

  • redis-6380.conf:做爲6380這臺實例的配置文件服務器

  • redis-6381.conf:做爲6381這臺實例的配置文件ide

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

二、修改6379這臺實例的配置文件redis-6379.conf,由於端口6379默認就是 Redis 的端口,因此只須要指定該實例的持久化片區(文件)便可。watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=測試

三、修改6380實例的配置文件redis-6380.confspa

  • 修改該實例佔用的端口爲6380線程

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= 

  • 修改pid對象

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • 修改dump文件名

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

四、修改6381實例的配置文件redis-6381.conf

  • 修改該實例佔用的端口爲6381

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • 修改pid

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • 修改dump文件名

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

redis-6380.conf 與 redis-6381.conf 配置步驟同樣的,只是配置的值不同。

 

0x03:啓動與測試:

一、分別啓動3臺 Redis 實例

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

二、測試

  Redis分區有兩種方式,對既定的 key 有不一樣的方式來選擇這個 key 存放到哪一個實例中,也就是說有不一樣的算法來映射某個 key 到某個 Redis 的實例中。

  • 最簡單的分區方式爲範圍分區,就是映射必定範圍的對象到特定的 Redis 實例。好比,ID 從0到10000的用戶會保存到實例 R0,ID 從10001到 20000的用戶會保存到 R1,以此類推。

  • 另外一種方式是 hash 一致算法實現分區,對 key 值進行 hash 一致性計算後獲得結果,最終將數據保存到某一臺 Redis 實例中。

測試方案一:基於 jedis jar

方法中定義了一個redis分片的鏈接池,分別添加用於測試的三個節點實例,而後向redis中增長10個記錄。

    //定義redis的配置
    PoolConfig poolconfig = new PoolConfig();
    poolconfig.setMaxTotal(1000);  //表示redis的最大鏈接數——最大1000個線程
    poolconfig.setMinIdle(5);  //表示最小空閒數量
    //定義redis的多個節點機器
    List<JedisShardInfo> list = new ArrayList<>();
    //爲集合添加參數
    list.add(new JedisShardInfo("192.168.161.139", 6379));
    list.add(new JedisShardInfo("192.168.161.139", 6380));
    list.add(new JedisShardInfo("192.168.161.139", 6381));
    //定義redis分片鏈接池
    ShardedJedisPool jedisPool = new ShardedJedisPool(poolconfig, list);
    //獲取鏈接操做redis
    ShardedJedis shardedJedis = jedisPool.getResource();
    //向redis中添加20個記錄查看分片結果
    for(int i = 0; i < 10; i++){
        //增長的記錄格式爲   key=NUM_i   value=i
        shardedJedis.set("NUM_"+i, ""+i);

經過 redis-cli 客戶端分別鏈接到這三臺 Redis 實例。結果發現10個記錄中有1個分到了6379區,3個分到了6380區,另外6個分到了6381區,由於是採用記錄的 key 值來進行 hash 一致性算法來肯定記錄的存放區域,因此即便從新分區都不會改變記錄的存放地址,因此仍然能夠根據 key 值來獲取到對應的 value 值。

測試方案一:基於 Spring

  • 配置文件redis.properties

# 配置Redis分片實例
redis.nodes = 192.168.161.139:6379,192.168.161.139:6380,192.168.161.139:6381
  • RedisConfig配置類

@Configuration   //標識我是一個配置類 通常與@Bean註解聯用
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
     @Value("${redis.nodes}")
     private String nodes;   //node,node,node

     @Bean
     public ShardedJedis shardedJedis(){
         List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
         String[] nodeArray = nodes.split(",");
         for( String node : nodeArray){   // node=host:port
             String host = node.split(":")[0];
             int port = Integer.parseInt(node.split(":")[1]);
             JedisShardInfo info = new JedisShardInfo(host,port);
             shards.add(info);
         }
         return new ShardedJedis(shards);
     }
}

分區的不足:

  • 分區是多臺 Redis 共同做用的,若是其中一臺出現了宕機現象,則整個分片都將不能使用,雖然是在必定程度上緩減了內存的壓力,可是沒有實現高可用。

  • 涉及多個 key 的操做一般是不被支持的。舉例來講,當兩個 set 映射到不一樣的Redis 實例上時,就不能對這兩個set執行交集操做。

  • 涉及多個 key 的 Redis事務不能使用。

  • 當使用分區時,數據處理較爲複雜,好比須要處理多個 rdb / aof 文件,而且從多個實例和主機備份持久化文件。

 高可用的解決方案

  • 哨兵主從複製實現高可用

  • 集羣模式

相關文章
相關標籤/搜索