分區就是將數據分割到多個Redis實例,所以每一個實例只保存一部分key - value,每個 Redis 實例的 key 的一個子集。node
若是隻使用一個 Redis 實例時,那麼這個 Redis 實例保存了服務器中所有的緩存數據,這樣會有很大風險,若是單臺 Redis 服務宕機了將會影響到整個服務。解決方案能夠採用分片 / 分區的技術,將原來一臺服務器維護的整個緩存,換爲由多臺服務器共同維護內存空間。redis
採用在一臺主機上實現分片的方式,因此只須要在該主機上配置啓動三臺 Redis 的實例。由於 Redis 默認使用的端口號爲6379,因此這裏分別使用637九、6380以及6381三個端口來實現。算法
一、進入到 Redis 的安裝目錄下,建立一個 shard 文件夾,而後將 Redis 的配置文件 redis.conf 複製一份,取名爲redis-6379.conf ( 做爲6379這臺實例的配置文件 )。而後將該文件移動到shard文件夾下,再將 redis-6379.conf 複製兩份。緩存
redis-6380.conf:做爲6380這臺實例的配置文件服務器
redis-6381.conf:做爲6381這臺實例的配置文件ide
二、修改6379這臺實例的配置文件redis-6379.conf,由於端口6379默認就是 Redis 的端口,因此只須要指定該實例的持久化片區(文件)便可。測試
三、修改6380實例的配置文件redis-6380.confspa
修改該實例佔用的端口爲6380線程
修改pid對象
修改dump文件名
四、修改6381實例的配置文件redis-6381.conf
修改該實例佔用的端口爲6381
修改pid
修改dump文件名
一、分別啓動3臺 Redis 實例
二、測試
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 文件,而且從多個實例和主機備份持久化文件。
高可用的解決方案
哨兵主從複製實現高可用
集羣模式