redis分片

来源:互联网 发布:什么牌的网络机顶盒好 编辑:程序博客网 时间:2024/06/04 19:00

1.Redis分片是指将数据拆分到多个redis实例

2.一种常用的分片方式叫做一致性哈希分片:

步骤如下:

 部署2个Redis master节点。

ShardedJedisPool连接Redis maser节点,并将数据根据一致性哈希算法存放到不同的master节点,从而达成数据分片。

Jedis分片连接池

package com.jd.redis.client; import Java.util.ArrayList;import java.util.List; import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.JedisShardInfo;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPool;import redis.clients.util.Hashing;import redis.clients.util.Sharded; publicclass RedisShardPoolTest {    static ShardedJedisPoolpool;    static{        JedisPoolConfig config =new JedisPoolConfig();//Jedis池配置        config.setMaxActive(500);//最大活动的对象个数          config.setMaxIdle(1000 * 60);//对象最大空闲时间          config.setMaxWait(1000 * 10);//获取对象时最大等待时间          config.setTestOnBorrow(true);        String hostA = "10.10.224.44";          int portA = 6379;          String hostB = "10.10.224.48";          int portB = 6379;        List<JedisShardInfo> jdsInfoList =new ArrayList<JedisShardInfo>(2);        JedisShardInfo infoA = new JedisShardInfo(hostA, portA);        infoA.setPassword("redis.360buy");        JedisShardInfo infoB = new JedisShardInfo(hostB, portB);        infoB.setPassword("redis.360buy");        jdsInfoList.add(infoA);        jdsInfoList.add(infoB);               pool =new ShardedJedisPool(config, jdsInfoList, Hashing.MURMUR_HASH,Sharded.DEFAULT_KEY_TAG_PATTERN);    }       /**     * @param args     */    publicstaticvoid main(String[] args) {        for(int i=0; i<100; i++){           String key =generateKey();           //key += "{aaa}";           ShardedJedis jds =null;           try {               jds =pool.getResource();               System.out.println(key+":"+jds.getShard(key).getClient().getHost());               System.out.println(jds.set(key,"1111111111111111111111111111111"));           }catch (Exception e) {               e.printStackTrace();           }           finally{               pool.returnResource(jds);           }        }    }     privatestaticintindex = 1;    publicstatic String generateKey(){        return String.valueOf(Thread.currentThread().getId())+"_"+(index++);    }}

通过执行结果会发现这100条数据会被分开存放到10.7.12.52和10.7.112.52机器上的master节点中,查看源码会发现jds.set(key,value)方法会调用jds.getShared(key)来根据key的hash值来获取该key应该存放到那个节点上。

3.分片的不同实现:

⑴客户端分片 客户端直接选择正确的节点来写入和读取指定值。

⑵代理协助分片 我们的客户端发送请求到一个可以理解 Redis协议的代理上代理会根据配置好的分片模式,来保证转发我们的请求到正确的 Redis实例,并返回响应给客户端。RedisMemcached的代理Twemproxy实现了代理协助的分片。

查询路由(Query routing)意味着,你可以发送你的查询到一个随机实例,这个实例会保证转发你的查询到正确的节点。Redis集群在客户端的帮助下,实现了查询路由的一种混合形式(请求不是直接从Redis实例转发到另一个,而是客户端收到重定向到正确的节点)

4.分片的缺点

涉及多个键的操作通常不支持。例如,你不能对映射在两个不同Redis服务器上的键执行交集。

涉及多个键的事务不能使用。

数据处理变得更复杂,例如,你需要处理多个RDB/AOF文件,备份数据时你需要聚合多个实例和主机的持久化文件。

Redis目前不支持动态分片操作,扩容和缩容操作都会比较复杂,尤其分片操作部署在客户端时,需要重新配置和启动客户端。在使用过程中缩容用的不多,扩容可以采用后面介绍的预分片策略来缓解此问题。

5.预分片技术

我们已经知道分片存在的一个问题,除非我们使用 Redis作为缓存,增加和删除节点是一件很棘手的事情,使用固定的键和实例映射要简单得多。

然而,数据存储的需求可能一直在变化。今天我可以接受 10Redis 节点(实例),但是明天我可能就需要50个节点。

因为 Redis只有相当少的内存占用(footprint)而且轻量级(一个空闲的实例只是用1MB内存),一个简单的解决办法是一开始就开启很多的实例。即使你一开始只有一台服务器,你也可以在第一天就决定生活在分布式的世界里,使用分片来运行多个Redis实例在一台服务器上。

你一开始就可以选择很多数量的实例。例如,32或者64 个实例能满足大多数的用户,并且为未来的增长提供足够的空间。

这样,当你的数据存储需要增长,你需要更多的 Redis服务器,你要做的就是简单地将实例从一台服务器移动到另外一台。当你新添加了第一台服务器,你就需要把一半的Redis 实例从第一台服务器搬到第二台,如此等等。

使用 Redis复制,你就可以在很小或者根本不需要停机时间内完成移动数据:

· 在你的新服务器上启动一个空实例。

· 移动数据,配置新实例为源实例的从服务。

· 停止你的客户端。

· 更新被移动实例的服务器 IP 地址配置。

· 向新服务器上的从节点发送 SLAVEOF NO ONE 命令。

· 以新的更新配置启动你的客户端。

· 最后关闭掉旧服务器上不再使用的实例。



原创粉丝点击