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;

}

}

Redis的分片技术

2.1 分片的配置

2.1.1 分片的概念

说明:早期如果使用一台redis时,其中保存的是服务器中全部的缓存数据.这样都放到一台服务器中会有风险,如果单台服务器宕机将直接影响整个服务.

策略:采用分片的技术,将原来由一台服务器维护整个缓存,现在换为由多台服务器共同维护整个缓存.假设之前一台服务器维护的内存数据量在9G.现在如果采用分片技术使用3台服务器共同维护内存空间,每台服务器维护3G内存.

好处:1.提高每台服务器的响应时间.

2.容灾性较好.

2.1.2 创建shard文件夹

  1. 先关机

redis-cli -p 6379 shutdown

  1. 创建shard文件夹

mkdir shard

  1. 复制文件

Cp 需要复制的文件名称  新建文件名称

  1. 移动文件

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 分片的缺点

  1. 使用分片时是多台redis一起使用的,.如果其中有某台机器出现宕机现象.则整个分片将不能执行.
  2. 虽然有分片技术能在一定程度上缓解内存的压力.但是没有实现高可用.

2.4.2 哨兵机制

说明:

0.先配置主从复制 6379当主机  6380 6381当从机

  1. 首先需要准备奇数(3)台哨兵
  2. 哨兵会实时的向主机发送心跳检测.如果主机出现长时间没有响应的情况

则判断主机死亡.

  1. 如果主机死亡,则从主机中配置的从机进行投票选举.
  2. 2台从机中由哨兵负责投票票数多着升级成为新的Master主机(6380)
  3. 另外的一台从机(6381)就会挂载到新的Master(6380)主机中
  4. 当原来的主机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

注意:

当配置了哨兵之后,将不能执行分片的代码,因为哨兵配置了主从,从机不允许进行写库操作.

但是分片的redis都是Master.与哨兵冲突.所以分开测试

redis分片和哨兵的更多相关文章

  1. Redis分片(分区)

    分区的概念 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集. 如果只使用一个redis实例时,其中保存了服务器中全部的缓存数据,这样会有很大风险,如果单台redis服 ...

  2. redis 主从、哨兵、集群

    出处: redis主从复制和哨兵 Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式 一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步 ...

  3. Redis——(主从复制、哨兵模式、集群)的部署及搭建

    Redis--(主从复制.哨兵模式.集群)的部署及搭建 重点: 主从复制:主从复制是高可用redis的基础,主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复. 哨兵和集群都是 ...

  4. Redis架构之哨兵机制与集群

    Redis架构之哨兵机制与集群 哨兵机制 1.介绍: Sentinel(哨兵)是redis高可用性解决方案:由一个或多个由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个 ...

  5. redis主从配置+哨兵模式

    1.搭建redis主从,一个master两个slave,加一个哨兵监听(sentinel),可以新建三个虚拟机,模拟环境,我的电脑没那么多虚拟机,就在一台虚拟机上弄的. 2.安装redis,如果是三台 ...

  6. Redis 部署主从哨兵 C#使用,实现自动获取redis缓存 实例1

    源码示例下载链接: https://pan.baidu.com/s/1eTA63T4 密码: un96 实现目标:windows 下安装 一台master服务 一台salve redis服务器 并且哨 ...

  7. 关于redis主从|哨兵|集群模式

    关于redis主从.哨兵.集群的介绍网上很多,这里就不赘述了. 一.主从 通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或少量损失)数据,因为持久化会把内存中数据保存到硬盘上,重 ...

  8. 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 ...

  9. 自动配置redis主从和哨兵

    redis shell  每次创建redis主从和哨兵服务,文件夹要复制好几个,配置文件改一大堆.繁琐还容易出错,就想通过shell脚本自动帮我配置好端口以及文件,下面就是脚本内容: redis-to ...

随机推荐

  1. HDU - 4496 City 逆向并查集

    思路:逆向并查集,逆向加入每一条边即可.在获取联通块数量的时候,直接判断新加入的边是否合并了两个集合,如果合并了说明联通块会减少一个,否则不变. AC代码 #include <cstdio> ...

  2. Machine Learning|Andrew Ng|Coursera 吴恩达机器学习笔记

    Week1: Machine Learning: A computer program is said to learn from experience E with respect to some ...

  3. 安装apache报没有找到VCRUNTIME40.dll错误

    解决办法 在Windows下运行最新版的Apache和php7都需要Visual C++Redistributable 2015,而之前的版本不需要那么高的,这个组件是运行Visual Studio ...

  4. ubuntu16.04卸载软件

    root@test:/# dpkg -l | grep cobbler root@test:/# sudo dpkg --purge cobbler

  5. 迁移学习︱艺术风格转化:Artistic style-transfer+ubuntu14.0+caffe(only CPU)

    说起来这门技术大多是秀的成分高于实际,但是呢,其也可以作为图像增强的工具,看到一些比赛拿他作训练集扩充,还是一个比较好的思路.如何在caffe上面实现简单的风格转化呢? 好像网上的博文都没有说清楚,而 ...

  6. 利用squid 反向代理提高网站性能

    部分转自:http://www.ibm.com/developerworks/cn/linux/l-cn-squid/ Squid 反向代理的实现原理 目前有许多反向代理软件,比较有名的有 Nginx ...

  7. 关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法

    关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法 题设: 经常使用FusionCharts图表的朋友可能会遇到这个问题.就是在FusionCharts显示的时候有时候 ...

  8. strcmp函数实现

    /* 功能:比较字符串s1和s2大小. 一般形式:int strcmp(字符串1,字符串2) 说明: 当s1<s2时,返回-1 当s1=s2时,返回 0 当s1>s2时,返回 1 即两个字 ...

  9. linux2.6硬盘扇区直接读写程序

    下面的程序可以在linux2.6内核直接读写硬盘的指定扇区,也是根据网上一个朋友的做法做了修改的: 有两个不是很明白的地方就是:1.bd_claim函数的使用,这个是个递归函数,像是匹配内存指针和设备 ...

  10. Codeforces Round #454 D. Seating of Students

    分三类 1 1: 一个就好了 3 3:特殊讨论下 或 : 第一行奇序号的数放前面,偶序号的数放后面,第二行奇序号的数放前面,偶序号的数放后面,第二行依次类推 有点难写,真的菜 #include< ...