redis分片和哨兵
1 Redis的使用
1.1 Redis入门案例
1.1.1 什么样的数据使用缓存
说明:使用缓存其实为了减少用户查询数据库的时间.如果数据频繁的变更.不适用缓存.缓存中的数据应该保存修改频率不高的数据.
例如:商品信息/邮编/省/市/县
1.2 Redis入门案例
1.2.1 导入jar包
说明:Jedis是java操作Redis的API工具包
<jedis.version>2.6.2</jedis.version>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
导入jar包文件之后将parent Install
1.2.2 代码测试
//测试redis操作
@Test
public void test01(){
/**
* 创建Jedis工具类
* 参数说明
* host:表示redis的主机ip
* port:表示redis的端口
*/
Jedis jedis = new Jedis("192.168.126.142", 6379);
//向redis中插入数据
jedis.set("tomcat", "tomcat猫");
System.out.println(jedis.get("tomcat"));
}
1.3 商品分类缓冲操作
1.3.1 需求说明
说明:用户在获取商品分类目录时每次都需要查询数据库.这样的操作效率不高.
可以将用户的分类信息插入到缓冲中,如果用户再次获取直接从缓存中获取数据即可.
1.4 将jedis交个spring管理
说明:如果将jedis直接写死到业务层,会造成代码的耦合,.所以通过spring的方式进行管理.如果需要进行依赖注入.
1.4.1 编辑配置文件
<!--通过spring的方式管理jedis
Jedis jedis = new Jedis("192.168.126.142", 6379);
补充:有时由于没有导入源码则新生成的方法中不会出现方法参数名称.而只有参数的类型
例如:String arg0,int arg1,arg2.
这样如果采用name的方式进行注入时可能会产生问题.
所以建议使用index下标进行参数赋值.
源码构造方法:
public Jedis(final String host, final int port)
问题:
通过构造注入的形式,可以通过参数的个数准确的匹配类中的方法.
如果参数个数形同时,切记需要通过类型区别,否则注入失败.
因为spring不知道到底应该调用哪个方法!!!
-->
<bean id="jedis" class="redis.clients.jedis.Jedis">
<constructor-arg index="0" value="${redis.host}"
type="java.lang.String"/>
<constructor-arg index="1" value="${redis.port}"
type="int"/>
</bean>
1.4.2 创建reids.properties文件
redis.host=192.168.126.142
redis.port=6379
1.4.3 Spring加载配置文件
1.5 商品分类缓冲实现
1.5.1 修改POJO对象
@Table(name="tb_item_cat")
//忽略未知属性 在爬虫时经常使用
@JsonIgnoreProperties(ignoreUnknown=true)
说明:由于Catlist集合在进行转化JSON时,调用get方法生成JSON数据.所以成功的JSON串格式如下
但是将JSON串转化为对象时,ObjectMapper会根据JSON的全部的的key值调用set方法为对象赋值.由于state和text属性是为了满足EasyUI格式时新增的.对实际业务不产生作用.所以应该告诉ObjectMapper.当执行到setState和setText时应该忽略这项操作.即添加@JsonIgnoreProperties(ignoreUnknown=true).忽略未知属性
@Service
public class ItemCatServiceImpl implements ItemCatService {
// 定义格式转化工具
private static final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private Jedis jedis;
@Override
public List<ItemCat> findItemCat() {
// 调用通用Mapper的方法
// 如果查询全部数据则不需要设定参数直接为null
return itemCatMapper.select(null);
}
/**
* 将商品分类信息插入到缓冲中 思路: redis中通过key-value 1.当用户查询数据时首先应该从缓存中获取数据
* 2.如果数据不为null,则代表缓存中有该数据.数据类型为JSON a.需要将JSON串转化为对象后返回给用户
* 3.如果数据为null,表示缓存中没有改数据.则需要连接数据库进行查询. a.将查询到的数据,转化为JSON存入redis中,方便下次使用.
*/
@Override
public List<ItemCat> findItemCatByParentId(Long parentId) {
// 1.定义查询的key值
String key = "ITEM_CAT_" + parentId;
// 2.根据key值查询缓存数据
String dataJSON = jedis.get(key);
// 最后定义公用的List集合
List<ItemCat> itemCatList = new ArrayList<ItemCat>();
try {
// 3判断返回值是否含有数据
if (StringUtils.isEmpty(dataJSON)) {
// 证明缓存中没有数据,则通过数据库查询数据
ItemCat itemCat = new ItemCat();
itemCat.setParentId(parentId); // 设定父级Id
itemCat.setStatus(1); // 设定为正常的数据 1
itemCatList = itemCatMapper.select(itemCat);
// 将返回数据转化为JSON串[{},{},{}]
String jsonResult = objectMapper.writeValueAsString(itemCatList);
// 将数据存入缓存中
jedis.set(key, jsonResult);
} else {
// 表示数据不为空 需要将JSON串转化为List<ItemCat>集合对象
// [{},{},{}] {id:1,name:"tom"}
ItemCat[] itemCats = objectMapper.readValue(dataJSON, ItemCat[].class);
for (ItemCat itemCat : itemCats) {
// 向集合中赋值
itemCatList.add(itemCat);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return itemCatList;
}
}
2 Redis的分片技术
2.1 分片的配置
2.1.1 分片的概念
说明:早期如果使用一台redis时,其中保存的是服务器中全部的缓存数据.这样都放到一台服务器中会有风险,如果单台服务器宕机将直接影响整个服务.
策略:采用分片的技术,将原来由一台服务器维护整个缓存,现在换为由多台服务器共同维护整个缓存.假设之前一台服务器维护的内存数据量在9G.现在如果采用分片技术使用3台服务器共同维护内存空间,每台服务器维护3G内存.
好处:1.提高每台服务器的响应时间.
2.容灾性较好.
2.1.2 创建shard文件夹
- 先关机
redis-cli -p 6379 shutdown
- 创建shard文件夹
mkdir shard
- 复制文件
Cp 需要复制的文件名称 新建文件名称
- 移动文件
mv redis-6379.conf shard/
2.1.3 修改redis.conf文件
1.修改6379
2.修改6380
vim redis-6380.conf
3.修改6381
将上述步骤中的6379改为6381
2.1.4 启动多台redis实例
说明:通过redis-server redis-6379.conf等命令启动redis服务
2.2 分片技术的使用
2.2.1 分片入门案例
说明:现在需要同时操作3台redis实现缓存技术.
//测试分片技术
@Test
public void test02(){
//JedisPoolConfig
//定义redis的配置 poolConfig是过期类型
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(1000);//表示最大连接数
poolConfig.setMinIdle(5);//最小空间数量
//定义redis多个节点信息
List<JedisShardInfo> list =
new ArrayList<JedisShardInfo>();
//为集合添加参数
list.add(new JedisShardInfo("192.168.126.142", 6379));
list.add(new JedisShardInfo("192.168.126.142", 6380));
list.add(new JedisShardInfo("192.168.126.142", 6381));
//定义redis分片连接池
ShardedJedisPool jedisPool =
new ShardedJedisPool(poolConfig, list);
//获取连接操作redis
ShardedJedis shardedJedis = jedisPool.getResource();
shardedJedis.set("tom", "tomcat猫"); //表示数据的赋值
System.out.println(shardedJedis.get("tom"));//从redis中获取数据
}
2.2.2 分片测试
说明:将数据插入到redis中发现数据的分布不均匀
2.2.3 Hash一致性算法
说明:由于使用了分片的方式管理多个redis节点信息,那么redis节点信息中保存的数据其实是根据key值进行hash一致性计算后得出的结果.最终将数据保存到某一台redis中
说明:
根据hash一致性算法,根据指定的key值计算出对应的地址,同时将该数据动态挂载的redis节点中,如果根据key进行查询时,先经过Hash计算最终找到对应的节点,获取该key的值.
2.3 Spring管理redis分片
2.3.1 编辑配置文件
定义redis.perproties
redis.maxTotal=1000
redis.maxIdle=100
#表示每次链接时 验证连接是否有效
redis.testOnBorrow=true
#分别代码三台主机
redis.host1=192.168.126.142
redis.port1=6379
redis.host2=192.168.126.142
redis.port2=6380
redis.host3=192.168.126.142
redis.port3=6381
2.3.2 定义Spring的配置文件
说明:其实就是将测试代码按照spring的方式进行配置。
<!--每次都创建jedis对象性能较低 创建jedis线程池 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--定义连接总数 -->
<property name="maxTotal" value="${redis.maxTotal}"/>
<!--定义最大闲置资源 -->
<property name="maxIdle" value="${redis.maxIdle}"/>
<!--定义连接是否自动检测,如果连接不能使用则会新创建连接 -->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<!--定义6379主机 public JedisShardInfo(String host, int port) -->
<bean id="jedisShard1" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.host1}" type="java.lang.String"/>
<constructor-arg index="1" value="${redis.port1}" type="int"/>
</bean>
<!--定义6380主机 -->
<bean id="jedisShard2" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.host2}" type="java.lang.String"/>
<constructor-arg index="1" value="${redis.port2}" type="int"/>
</bean>
<!--定义6381主机 -->
<bean id="jedisShard3" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.host3}" type="java.lang.String"/>
<constructor-arg index="1" value="${redis.port3}" type="int"/>
</bean>
<!--定义分片连接池 final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards-->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="poolConfig"/>
<constructor-arg index="1">
<list>
<ref bean="jedisShard1"/>
<ref bean="jedisShard2"/>
<ref bean="jedisShard3"/>
</list>
</constructor-arg>
</bean>
2.3.3 修改redis配置文件
redis.maxTotal=1000
redis.maxIdle=100
#表示每次链接时 验证连接是否有效
redis.testOnBorrow=true
#分别代码三台主机
redis.host1=192.168.126.142
redis.port1=6379
redis.host2=192.168.126.142
redis.port2=6380
redis.host3=192.168.126.142
redis.port3=6381
2.3.4 编写工具service
@Service //spring开启包扫描时的路径为jt.com
public class RedisService {
@Autowired //redis的spring管理中配置bean标签
private ShardedJedisPool jedisPool;
//定义set方法
public void set(String key,String value){
//通过池获取对象
ShardedJedis shardedJedis = jedisPool.getResource();
//通过jedis操作数据
shardedJedis.set(key, value);
//将链接还回池中
jedisPool.returnResource(shardedJedis);
}
//定义get方法
public String get(String key){
ShardedJedis shardedJedis = jedisPool.getResource();
String value = shardedJedis.get(key);
jedisPool.returnResource(shardedJedis);
return value;
}
}
2.4 Redis哨兵机制
2.4.1 分片的缺点
- 使用分片时是多台redis一起使用的,.如果其中有某台机器出现宕机现象.则整个分片将不能执行.
- 虽然有分片技术能在一定程度上缓解内存的压力.但是没有实现高可用.
2.4.2 哨兵机制
说明:
0.先配置主从复制 6379当主机 6380 6381当从机
- 首先需要准备奇数(3)台哨兵
- 哨兵会实时的向主机发送心跳检测.如果主机出现长时间没有响应的情况
则判断主机死亡.
- 如果主机死亡,则从主机中配置的从机进行投票选举.
- 2台从机中由哨兵负责投票票数多着升级成为新的Master主机(6380)
- 另外的一台从机(6381)就会挂载到新的Master(6380)主机中
- 当原来的主机6379启动后,会成为新的主机6380的从机
2.5 配置主从复制
2.5.1 关闭之前的redis
说明:配置哨兵之前首先将原有的redis关闭
2.5.2 启动多个redis服务
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
2.5.3 查看redis信息
说明:进入redis客户端后,进入redis-6379客户端
执行命令:
2.5.4 实现主从挂载
进入到redis-cli -p 6380 后执行,实现主从挂载.将6380挂载到6379上
重复上述步骤将6381挂载到6379中
2.6 搭建哨兵
2.6.1 复制哨兵配置文件
cp sentinel.conf sentinel-6379.conf
2.6.2 移动配置文件到sentinel文件夹
mkdir sentinel
将sentinel-6379.conf 移动到sentinel中
mv sentinel-6379.conf sentinel
2.7 编辑哨兵配置文件
2.7.1 关闭保护模式:
sentinel.conf 哨兵的配置文件,将保护模式关闭的注释去掉
2.7.2 配置主机的ip
sentinel monitor mymaster 192.168.247.160 6379 1
1代表的含义:
超高半数的票数如果3台机器,半数为2 如果是5台机器半数为3
2.7.3 配置时间
表示master多少秒之后标记为down机
如果哨兵在规定的时间内内没有完成推举机制,则本次推举失败
2.7.4 哨兵启动
哨兵启动:可以通过控制台查配置信息
redis-sentinel sentinel6379.conf
2.7.5 哨兵测试:
当主机宕机后,哨兵会自动的推举出新的主机.旧的主机启动后,降为slave
3 注意:
当配置了哨兵之后,将不能执行分片的代码,因为哨兵配置了主从,从机不允许进行写库操作.
但是分片的redis都是Master.与哨兵冲突.所以分开测试
redis分片和哨兵的更多相关文章
- Redis分片(分区)
分区的概念 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集. 如果只使用一个redis实例时,其中保存了服务器中全部的缓存数据,这样会有很大风险,如果单台redis服 ...
- redis 主从、哨兵、集群
出处: redis主从复制和哨兵 Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式 一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步 ...
- Redis——(主从复制、哨兵模式、集群)的部署及搭建
Redis--(主从复制.哨兵模式.集群)的部署及搭建 重点: 主从复制:主从复制是高可用redis的基础,主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复. 哨兵和集群都是 ...
- Redis架构之哨兵机制与集群
Redis架构之哨兵机制与集群 哨兵机制 1.介绍: Sentinel(哨兵)是redis高可用性解决方案:由一个或多个由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个 ...
- redis主从配置+哨兵模式
1.搭建redis主从,一个master两个slave,加一个哨兵监听(sentinel),可以新建三个虚拟机,模拟环境,我的电脑没那么多虚拟机,就在一台虚拟机上弄的. 2.安装redis,如果是三台 ...
- Redis 部署主从哨兵 C#使用,实现自动获取redis缓存 实例1
源码示例下载链接: https://pan.baidu.com/s/1eTA63T4 密码: un96 实现目标:windows 下安装 一台master服务 一台salve redis服务器 并且哨 ...
- 关于redis主从|哨兵|集群模式
关于redis主从.哨兵.集群的介绍网上很多,这里就不赘述了. 一.主从 通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或少量损失)数据,因为持久化会把内存中数据保存到硬盘上,重 ...
- 9.Redis高可用-哨兵
9.Redis高可用-哨兵9.1 基本概念9.1.1 主从复制的问题9.1.2 高可用9.1.3 Redis Sentinel的高可用性9.2 安装和部署9.2.1 部署拓扑结构9.2.2 部署Red ...
- 自动配置redis主从和哨兵
redis shell 每次创建redis主从和哨兵服务,文件夹要复制好几个,配置文件改一大堆.繁琐还容易出错,就想通过shell脚本自动帮我配置好端口以及文件,下面就是脚本内容: redis-to ...
随机推荐
- iOS.Animations.by.Tutorials.v2.0汉化(二)
翻译自:iOS.Animations.by.Tutorials.v2.0 第一节(第1章) 动画属性 现在你已经看到了动画是多么的简单,你可能很想知道你的视图控件是怎么动起来的.本节将给你一个UIVi ...
- 使用static与const关键字时需要掌握的知识
static:1.不考虑类,static的作用: 1)第一个作用:隐藏.使得全局变量和函数对其它文件不可见,同时避免了不同文件的命名冲突. 2)第二个作用:默认初始化为0.未初始化的全局静 ...
- Android设置View抖动动画
在应用中,有时候我们要吸引用户去点击某些按钮,比如应用市场的推荐按钮,为了能够吸引用户主动点击而且不过分的打扰用户,最好的方法就是给我们想吸引用户注意的view添加一些抖动动画,比如这张图 这里我主要 ...
- Android可以拖动位置的ListVeiw
参考网址: 1.https://github.com/bauerca/drag-sort-listview 2.http://www.tuicool.com/articles/jyA3MrU
- strcpy函数
不调用C/C++库函数,编写strcpy()函数. char * my_strcpy(char *strDest,const char *strSrc) { char *p=strDest; whil ...
- dojo中获取表格中某一行的某个值
dojo中经常出现对表格中的某行进行操作,如单击某行修改.删除等.那怎样获取某行的唯一标示呢? 如查询表格中的某列有个userId,并且这个是唯一的,那么可以通过它来访问这一列 具体操作代码如下: v ...
- Linux显示USB设备
Linux显示USB设备 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ lsusb -tv /: Bus 08.Port 1: Dev 1, Class=ro ...
- Struts2(五)常量的配置
Struts2 常量大多在 默认的配置文件中已经配置好,但根据用户的需求不同,开发的要求不同,需要修改这些常量值,修改的方法就是在配置的文件对常量进行重新配置 在struts.xml 文件中使用< ...
- Linux系统 awk sed R脚本 python脚本传入变量
sed 传入变量: chrI="chr2";sed -n "/$chrI/p" clippointpos.csv #变量用$var表示,把sed的单引号变为双 ...
- “玲珑杯”ACM比赛 Round #4 B Best couple
一眼的KM,但是建图的时候记得不用的点设为0,点少的一边补齐,这个非常重要,因为KM追求完全匹配,如果无法完全匹配会非常慢 #include<bits/stdc++.h> using na ...