13_ redis数据库高可用

数据库高可用
1.1 数据库高可用说明
当数据库的主库宕机之后.如果没有高可用机制,则可能导致整个服务全部不能正常的使用.
解决策略: 双主模式(双机热备)

1.2 数据库双机热备实现
1.2.1 双机热备的说明
将2台数据库设置为双主模式.互为主从的结构.其中任意的数据库服务器既是主机.也是从机.
在这里插入图片描述

1.2.1 双机热备实现
规划:
之前配置:
192.168.126.129:3306 主机.
192.168.126.130:3306 从机.
优化后的配置
192.168.126.129:3306 主机.从机
192.168.126.130:3306 从机.主机

配置:
1).检查130 主机的状态信息
在这里插入图片描述
2).实现主从的挂载 操作的是129
/129 我是主机 现在当从机/
/实现主从挂载/
CHANGE MASTER TO MASTER_HOST=“192.168.126.130”,
MASTER_PORT=3306,
MASTER_USER=“root”,
MASTER_PASSWORD=“root”,
MASTER_LOG_FILE=“mysql-bin.000001”,
MASTER_LOG_POS=714;

/2.开启主从服务/
START SLAVE

/3.检查主从的状态/
SHOW SLAVE STATUS;

在这里插入图片描述
1.2.2 双机热备的测试
测试A: 修改129中的数据,检查130中是否实现了数据的同步!!
测试B: 修改130中的数据.检查129种是否实现了数据的同步!!!

1.3 数据库高可用实现
1.3.1 Mycat配置

1<mycat:schema xmlns:mycat="http://io.mycat/"> 2 3 <!--name属性是自定义的 dataNode表示数据库的节点信息 jtdb表示逻辑库--> 4 <schema name="jtdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="jtdb"/> 5 6 <!--定义节点名称/节点主机/数据名称--> 7 <dataNode name="jtdb" dataHost="localhost1" database="jtdb" /> 8 <!--参数介绍--> 9 <!--balance 0表示所有的读操作都会发往writeHost主机 --> 10 <!--1表示所有的读操作发往readHost和闲置的主节点中--> 11 <!--writeType=0 所有的写操作都发往第一个writeHost主机--> 12 <!--writeType=1 所有的写操作随机发往writeHost中--> 13 <!--dbType 表示数据库类型 mysql/oracle--> 14 <!--dbDriver="native" 固定参数 不变--> 15 <!--switchType=-1 表示不自动切换, 主机宕机后不会自动切换从节点--> 16 <!--switchType=1 表示会自动切换(默认值)如果第一个主节点宕机后,Mycat会进行3次心跳检测,如果3次都没有响应,则会自动切换到第二个主节点--> 17 <!--并且会更新/conf/dnindex.properties文件的主节点信息 localhost1=0 表示第一个节点.该文件不要随意修改否则会出现大问题--> 18 <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" 19 writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> 20 <heartbeat>select 1</heartbeat> 21 22 <!--配置第一台主机主要进行写库操作,在默认的条件下Mycat主要操作第一台主机在第一台主机中已经实现了读写分离.因为默认写操作会发往137的数据库.读的操作默认发往141.如果从节点比较忙,则主节点分担部分压力. 23 --> 24 <writeHost host="hostM1" url="192.168.126.129:3306" user="root" password="root"> 25 <!--读数据库1--> 26 <readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" /> 27 <!--读数据库2--> 28 <readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" /> 29 30 </writeHost> 31 32 <!--定义第二台主机 由于数据库内部已经实现了双机热备.--> 33 <!--Mycat实现高可用.当第一个主机137宕机后.mycat会自动发出心跳检测.检测3.--> 34 <!--如果主机137没有给Mycat响应则判断主机死亡.则回启东第二台主机继续为用户提供服务.--> 35 <!--如果137主机恢复之后则处于等待状态.如果141宕机则137再次持续为用户提供服务.--> 36 <!--前提:实现双机热备.--> 37 38 <writeHost host="hostM2" url="192.168.126.130:3306" user="root" password="root"> 39 <!--读数据库1--> 40 <readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" /> 41 <!--读数据库2--> 42 <readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" /> 43 </writeHost> 44 </dataHost> 45</mycat:schema>

1.3.2 上传配置文件
在这里插入图片描述
重启mycat.

在这里插入图片描述
1.3.3数据库高可用测试
测试策略:
1).启动服务器检查用户数据是否正确获取.
在这里插入图片描述
2).将Mysql数据库的主库宕机.检查数据是否正确获取
关闭mysql主机.

在这里插入图片描述
修改数据库记录:
在这里插入图片描述

3).将mysql数据库重启,检查mysql数据库是否实现数据的同步.
检查主库记录:

1.4 京淘项目Linux发布(终极)
1.4.1 发布架构图
在这里插入图片描述

1.4.2 项目打包部署
在这里插入图片描述

1.4.3 重启nginx服务器

在这里插入图片描述
1.4.4 京淘后台项目发布测试

在这里插入图片描述
2 Redis 缓存机制
2.1 准备工作
1).还原端口号信息
在这里插入图片描述
2).修改图片上传地址
在这里插入图片描述
3).修改HOSTS文件
在这里插入图片描述
4).修改nginx.conf文件
在这里插入图片描述
修改完成之后,重启nginx服务器.

2.2 为什么要引入缓存
说明:提供用户查询数据的速度.
在这里插入图片描述

2.3 缓存设计的因素
缓存的存储的数据结构应该 K-V结构. key是唯一标识符.
缓存的运行环境 应该让缓存运行在内存中.
缓存的开发语言 C语言开发
缓存中的内存优化策略 LRU算法/LFU算法
缓存数据有效性的设定 多久超时
如何防止内存数据丢失 数据落地(数据进行持久化操作)
2.4 Redis
2.4.1 Redis介绍
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

核心: 内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件
数据类型: 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)
处理速度: 写操作 8.6万/秒 读操作 11.2万/秒 平均10万/秒

2.5 Redis安装
2.5.1 上传安装包
在这里插入图片描述

2.5.2 解压安装包
命令:
1).tar -xvf redis-5.0.4.tar.gz
2).删除安装包,修改文件名称
在这里插入图片描述

2.5.3 安装Redis
说明:跳转到redis根目录中执行如下指令

make
make install
在这里插入图片描述

2.5.3 修改redis配置文件
1).编辑配置文件 vim redis.conf
在这里插入图片描述
2).注释IP绑定
在这里插入图片描述
3).关闭保护模式

在这里插入图片描述
4).开启后台启动
在这里插入图片描述

2.5.4redis常规命令
1).启动redis redis-server redis.conf
2).进入redis客户端
在这里插入图片描述
2).关闭redis redis-cli -p 6379 shutdown

小结
1.完成数据库高可用!!!
2.了解为什么需要使用redis
3.redis基本方法 开启 关闭等

2.6 Redis入门案例
2.6.1 引入jar包

1<!--spring整合redis --> 2 <dependency> 3 <groupId>redis.clients</groupId> 4 <artifactId>jedis</artifactId> 5 </dependency> 6 <dependency> 7 <groupId>org.springframework.data</groupId> 8 <artifactId>spring-data-redis</artifactId> 9 </dependency>

2.6.2 String类型的测试

1public class TestRedis { 2 3 /** 4 * 如果测试有误,则检查上午修改的三处配置文件. 重启redis. 5 * @throws InterruptedException 6 */ 7 @Test 8 public void testString() throws InterruptedException { 9 Jedis jedis = new Jedis("192.168.126.129",6379); 10 jedis.set("aaaa","123456"); 11 System.out.println(jedis.get("aaaa")); 12 13 //判断redis中的key是否存在 14 if(!jedis.exists("abc")) { 15 jedis.set("abc","123456"); 16 } 17 18 //为数据添加超时时间 19 jedis.set("h", "123"); 20 jedis.expire("h", 10); 21 Thread.sleep(2000); 22 System.out.println("剩余的存活时间:"+jedis.ttl("h")+"秒"); 23 24 } 25 26 27 /** 28 * 要求:如果key已经存在,则不允许修改!!! 29 * @throws InterruptedException 30 */ 31 @Test 32 public void testStringSetNX() throws InterruptedException { 33 Jedis jedis = new Jedis("192.168.126.129",6379); 34 jedis.flushAll(); //清空redis 35 jedis.setnx("abc", "123"); //只有当数据不存在时才会赋值. 36 jedis.setnx("abc", "456"); 37 System.out.println(jedis.get("abc")); 38 } 39 40 /** 41 * 虽然expire可以为数据添加超时时间,但是从宏观角度分析,该方法不具备原子性的操作 42 * 使用该方法可能存在风险. 43 * @throws InterruptedException 44 */ 45 @Test 46 public void testStringSetEx() throws InterruptedException { 47 Jedis jedis = new Jedis("192.168.126.129",6379); 48 jedis.flushAll(); //清空redis 49 jedis.setex("abc", 100, "123"); //保证了数据的原子性操作 50 } 51 52 /** 53 * 1.set操作时,如果该数据存在则不允许赋值 54 * 2.set操作的同时要求添加超时时间 55 * 3.上述的操作,必须同时成功或者同时失败 保证原子性操作. 56 * 57 * XX = "xx"; 当key存在时 才会赋值 58 NX = "nx"; 当key不存在时才会赋值. 59 PX = "px"; 添加超时时间的单位 毫秒 60 EX = "ex"; 秒 61 */ 62 @Test 63 public void testStringSet() throws InterruptedException { 64 Jedis jedis = new Jedis("192.168.126.129",6379); 65 jedis.flushAll(); //清空redis 66 SetParams params = new SetParams(); 67 params.nx().ex(60); 68 jedis.set("abc", "123456", params); 69 } 70}

2.7 商品分类缓存实现原理说明
2.7.1 什么样的数据添加缓存
说明: 变化范围不大的数据,并且需要被频繁查询的数据 可以添加缓存,
常见用法: 省/市/县/乡, 商品分类信息
在这里插入图片描述

2.7.2 缓存实现策略
在这里插入图片描述
说明:
1.商品分类信息采用redis方式进行缓存存取.
2.如果需要存储到Redis中,则必须准备 key(String)-value(String)
3.由于redis通常情况下使用String的数据类型.所以需要将key-value转化为String数据类型.
4.需要将返回值结果List对象转化为JSON数据.

2.8 ObjectMapper学习
2.8.1 入门案例

1public class TestObjectMapper { 2 3 @Test 4 public void testObject() throws JsonProcessingException { 5 //1.创建工具API对象 6 ObjectMapper objectMapper = new ObjectMapper(); 7 //2.封装转化对象 8 ItemDesc itemDesc = new ItemDesc(); 9 itemDesc.setItemId(1001L).setItemDesc("测试json转化") 10 .setCreated(new Date()).setUpdated(itemDesc.getCreated()); 11 //对象------JSON-------String字符串 12 //3.对象转化为JSON时,调用的是对象的get() 13 String json = objectMapper.writeValueAsString(itemDesc); 14 System.out.println(json); //{key:value,key2:value2} 15 16 //4.将json串转化为对象 调用的是对象的set方法为属性赋值.... 17 ItemDesc itemDesc2 = objectMapper.readValue(json, ItemDesc.class); 18 System.out.println(itemDesc2.toString()); 19 } 20 21 22 @Test 23 public void testList() throws JsonProcessingException { 24 //1.创建工具API对象 25 ObjectMapper objectMapper = new ObjectMapper(); 26 List<ItemDesc> list = new ArrayList<ItemDesc>(); 27 ItemDesc itemDesc1 = new ItemDesc(); 28 itemDesc1.setItemId(100L); 29 ItemDesc itemDesc2 = new ItemDesc(); 30 itemDesc2.setItemId(200L); 31 list.add(itemDesc1); 32 list.add(itemDesc2); 33 34 //测试list集合转化为JSON 35 String json = objectMapper.writeValueAsString(list); 36 System.out.println(json); 37 38 //测试json结构,能否转化为List集合 39 List<ItemDesc> list2 = objectMapper.readValue(json, list.getClass()); 40 System.out.println(list2); 41 } 42 43}

2.8.2 JSON转化的工具API封装
说明:该工具API主要的目的为了简化对象与JSON转化的过程.编辑如下的API

1//简化代码而生!! 2public class ObjectMapperUtil { 3 4 //定义一个常量对象 5 private static final ObjectMapper MAPPER = new ObjectMapper(); 6 7 //1.将对象转化为json串 8 public static String toJSON(Object target) { 9 10 String json = null; 11 try { 12 json = MAPPER.writeValueAsString(target); 13 } catch (JsonProcessingException e) { 14 e.printStackTrace(); 15 //将检查异常,转化为运行时异常!!!! 16 throw new RuntimeException(); 17 } 18 return json; 19 } 20 21 //2.将json串按照指定的类型转化为对象 22 //实现:传递什么类型,就返回什么对象 23 // <T> 定义泛型 24 public static <T> T toObj(String json,Class<T> target) { 25 T t = null; 26 try { 27 t = MAPPER.readValue(json, target); 28 } catch (JsonProcessingException e) { 29 e.printStackTrace(); 30 throw new RuntimeException(); 31 } 32 return t; 33 } 34}

2.9 Spring容器管理Redis对象
2.9.2 编辑pro文件
说明:在jt-common中添加配置文件.指定redis的链接地址

redis.host=192.168.126.129
redis.port=6379
在这里插入图片描述

2.9.1 编辑配置类
说明:如果需要将redis对象交给Spring容器管理则必须通过配置文件/配置类的形式管理.
在这里插入图片描述

1package com.jt.config; 2 3import org.springframework.beans.factory.annotation.Value; 4import org.springframework.context.annotation.Bean; 5import org.springframework.context.annotation.Configuration; 6import org.springframework.context.annotation.PropertySource; 7 8import redis.clients.jedis.Jedis; 9 10//代表早期的配置文件 11@Configuration 12@PropertySource("classpath:/properties/redis.properties") 13public class RedisConfig { 14 15 @Value("${redis.host}") 16 private String host; 17 @Value("${redis.port}") 18 private Integer port; 19 20 //bean注解 将生成的jedis对象交给Spring容器管理 21 @Bean 22 public Jedis jedis() { 23 24 return new Jedis(host,port); 25 } 26}

2.10 实现商品分类缓存
2.10.1 编辑ItemCatController

1/** 2 * url:http://localhost:8091/item/cat/list 3 * 参数: 当展现二三级信息时,会传递父级的Id信息,如果展现1级菜单,则应该设定默认值 4 * 返回值: List<EasyUITree> 5 */ 6 @RequestMapping("list") 7 public List<EasyUITree> findItemCatList 8 (@RequestParam(name="id",defaultValue="0")Long parentId){ 9 10 //1.查询一级商品分类信息,所以 11 //return itemCatService.findItemCatList(parentId); //数据库操作 12 return itemCatService.findItemCatCache(parentId); //缓存操作 13 }

2.10.2 编辑ItemCatService

1/** 2 * 思路: 3 * 1.定义查询redis的key, key要求唯一的 4 * 2.第一次查询先查询redis. 5 * 没有数据: 表示缓存中没有数据, 查询数据库,之后将数据保存到redis中 6 * 有数据: 证明缓存中有值, 直接返回给用户即可. 7 */ 8 @SuppressWarnings("unchecked") 9 @Override 10 public List<EasyUITree> findItemCatCache(Long parentId) { 11 String key = "ITEM_CAT_PARENTID_"+parentId; 12 List<EasyUITree> treeList = new ArrayList<>(); 13 //1.判断redis中是否有记录 14 if(jedis.exists(key)) { 15 //表示redis中有记录. 16 String json = jedis.get(key); 17 treeList = 18 ObjectMapperUtil.toObj(json, treeList.getClass()); 19 System.out.println("实现redis缓存查询"); 20 }else { 21 //redis中没有记录,需要先查询数据库. 22 treeList = findItemCatList(parentId); 23 //将数据库记录转化为json之后保存到redis中 24 String json = ObjectMapperUtil.toJSON(treeList); 25 jedis.set(key, json); 26 System.out.println("第一次查询数据库!!!!!"); 27 } 28 29 return treeList; 30 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Nginx keepalive 双机热备 主主主从模式

Nginxkeepalived高可用双机热备(主从模式/双主模式)基础介绍负载均衡技术对于一个网站尤其是大型网站的web服务器集群来说是至关重要的!做好负载均衡架构,可以实现故障转移和高可用环境,避免单点故障,保证网站健康持续运行。   关于负载均衡介绍,可以参考:linux负载均衡总结性说明(四层负载/七层负载)

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid