在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Redis作为承担缓存作用的数据库,一般会应用在高并发的场景里,而在这些高并发应用场景的数据库层面还会用到其他数据库的组件或集群以提升性能,比如用MySQL主从集群实现读写分离效果、用MyCAT组件实现分库分表的功能。另外,Redis本身会以集群的形式对外提供缓存服务。 1、用Docker搭建MySQL主从集群这里用Docker容器搭建如下图所示的MySQL主从集群。
具体搭建的步骤如下: 1.1 拉取mysql镜像 开启一个命令窗口,在其中运行 1.2 创建配置文件夹新建 1.3 编写主服务器的配置文件信息在/root/redisconf/masterMySQL/conf目录里新建一个my.cnf文件,在其中编写针对主mysql服务器的配置信息,主mysql服务器在启动时会读取其中的配置,具体代码如下所示: [mysqld] pid-file =/var/run/mysqld/mysqld.pid socket =/var/run/mysqld/mysqld.sock datadir =/var/lib/mysql server-id =1 log-bin=mysql-master-bin
1.4 启动mysql主服务器的容器docker run -itd --privileged=true -p 3306:3306 \ --name myMasterMysql -e MYSQL_ROOT_PASSWORD=123456\ -v /root/redisconf/masterMySQL/conf:/etc/mysql/conf.d\ -v /root/redisconf/masterMySQL/data:/var/lib/mysql mysql:latest
查看启动的容器:
由此能确认myMasterMysql启动成功。
可以看到,这里是172.17.0.2,这也是主mysql服务器所在的Ip地址。 1.5 观察主服务器状态 运行 进入mysql服务器之后,再运行
可以看到,主从集群同步所用到的日志文件是 1.6 配置mysql从服务器在/root/redisconf/slaveMaster/conf目录里,新建一个名为my.cnf的文件,编写针对从MYSQL服务器的配置信息。同样的,从Mysql服务器在启动时也会读取其中的配置,具体代码如下所示。 [mysqld] pid-file=/var/run/mysqld/mysqld.pid socket=/var/run/mysqld/mysqld.sock datadir=/var/lib/mysql server-id=2 log-bin=mysql-slave-bin
1.7 启动mysql从服务器docker run -itd --privileged=true -p 3316:3306\ --name mySlaveMysql -e MYSQL_ROOT_PASSWORD=123456\ -v /root/redisconf/slaveMySQL/conf:/etc/mysql/conf.d\ -v /root/redisconf/slaveMySQL/data:/var/lib/mysql\ mysql:latest 这里在-p参数之后使用主机的3316端口映射Docker容器的3306端口,因为之前主mysql服务器的Docker容器已经映射到了3306端口,其他的参数和之前创建myMasterMysql容器时很相似,就不再重复了。 随后
确认链接后,通过 1.8 确认主从关系change master to master_host='172.17.0.2',master_port=3306,\ master_user='root',master_password='123456',\ master_log_pos=156,\ master_log_file='mysql-master-bin.000003';
运行完成后,需要再运行
此时如果再到主mysql服务器里运行 主库 从库 2、准备数据由于已经成功地设置了主从复制模式,因此如下地建表和插入语句都只需要在主库里运行。 2.1 创建数据库create database redisDemo 进入redisDemo数据库 2.2 创建student数据表create table student( id int not null primary key, name char(20), age int, score float ); 2.3 向student表插入几条数据insert into student(id,name,age,score) values(1,'Peter',18,100); insert into student(id,name,age,score) values(2,'Tom',17,98); insert into student(id,name,age,score) values(3,'John',17,99);
从库里查看 3、用Java代码读写MySQL集群和Redis3.1 引入redis和mysql依赖<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency>
3.2 代码整合MySQLClusterDemo.java import redis.clients.jedis.Jedis; import java.sql.*; public class MySQLClusterDemo { //创建操作Redis和数据库的对象 private Jedis jedis; private Connection masterConn; //连接主库的对象 private Connection slaveConn; //连接从库的对象 PreparedStatement masterPs=null; //对主库进行操作的对象 PreparedStatement slavePs=null; //对从库进行操作的对象 //初始化环境 private void init(){ //MYSQL的连接参数 String mySQLDriver="com.mysql.cj.jdbc.Driver"; String masterUrl="jdbc:mysql://192.168.159.33:3306/redisDemo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"; String slaveUrl="jdbc:mysql://192.168.159.33:3316/redisDemo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"; String user="root"; String pwd="123456"; try{ Class.forName(mySQLDriver); masterConn= DriverManager.getConnection(masterUrl,user,pwd); slaveConn= DriverManager.getConnection(slaveUrl,user,pwd); jedis=new Jedis("192.168.159.33",6379); }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } private void insertData(){ //是向主MySQL服务器插入数据 try{ masterPs=masterConn.prepareStatement("insert into student(id,name,age,score) values(10,'Frank',18,100)"); masterPs.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } private String getNameByID(String id){ String key="Stu"+id; String name=""; //如果存在于Redis,就先从Redis里获取 if(jedis.exists(key)){ System.out.println("ID:"+key+" exists in Redis"); name=jedis.get(key); System.out.println("Name is :"+jedis.get(key)); return name; }else{ //如果没在Redis里,就到从MySQL里去读 try { slavePs=slaveConn.prepareStatement("select name from student where id=10"); ResultSet rs=slavePs.executeQuery(); if(rs.next()){ System.out.println("ID: "+key+" exists in Slave MySQL"); name=rs.getString("name"); System.out.println("Name is: "+name); //放入Redis缓存 jedis.set(key,name); } return name; }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } return name; } public static void main(String[] args) { MySQLClusterDemo tool=new MySQLClusterDemo(); tool.init(); tool.insertData(); //场景1 没有从Redis中找到,就到从MySQL服务器中去读 System.out.println(tool.getNameByID("10")); //场景2,当前ID=10的数据已存在于Redis,所有直接读缓存 System.out.println(tool.getNameByID("10")); } } 运行结果 4、MySQL主从集群整合Redis主从集群 上面的mysql主从集群至整合了一个Redis主机,在这种模式里如果Redis服务器失效了,那么整个缓存可能都会失效。可以在次基础上引入Redis主从复制集群,以提升缓存的可用性以及性能,改进后的框架图如下所示。 应用程序同样是向主mysql服务器里写数据,这些数据同步到从mysql数据库里。 应用程序先到“从Redis服务器”里读取缓存,如果找不到,就再到从mysql数据库里去读。 如果从“从mysql数据库”里读到数据,那么需要写入“主Redis”,而根据Redis集群的主从复制机制,该数据会被写入“从Redis服务器”。这种针对Redis集群的读写分离机制能提升读写缓存的性能。 4.1 搭建Redis主从复制集群4.1.1 创建redis-master容器 docker run -itd --name redis-master -p 6379:6379 redis:latest 4.1.2 创建resis-slave容器 docker run -itd --name redis-slave -p 6380:6379 redis:latest 4.1.3 查看redis服务器的ip docker inspect redis-master
可以看到,redis-master的ip地址为172.17.0.4 4.1.4 主从配置 在redis-slave容器的窗口里,通过 slaveof 172.17.0.4 6379 运行完该命令后,在redis-slave客户端里再次运行
4.2、代码整合MySQLClusterImprovedDemo.java import redis.clients.jedis.Jedis; import java.sql.*; public class MySQLClusterImprovedDemo { //创建操作Redis和数据库的对象 private Jedis masterJedis; //指向主Redis服务器 private Jedis slaveJedis; //指向从Redis服务器 private Connection masterConn; //连接主库的对象 private Connection slaveConn; //连接从库的对象 PreparedStatement masterPs=null; //对主库进行操作的对象 PreparedStatement slavePs=null; //对从库进行操作的对象 private void init(){ //MYSQL的连接参数 String mySQLDriver="com.mysql.cj.jdbc.Driver"; String masterUrl="jdbc:mysql://192.168.159.33:3306/redisDemo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"; String slaveUrl="jdbc:mysql://192.168.159.33:3316/redisDemo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"; String user="root"; String pwd="123456"; try{ Class.forName(mySQLDriver); masterConn= DriverManager.getConnection(masterUrl,user,pwd); slaveConn= DriverManager.getConnection(slaveUrl,user,pwd); masterJedis=new Jedis("192.168.159.33",6379); slaveJedis=new Jedis("192.168.159.33",6380); }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } private void insertData(){ //是向主MySQL服务器插入数据 try{ masterPs=masterConn.prepareStatement("insert into student(id,name,age,score) values(10,'Frank',18,100)"); masterPs.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } private String getNameByID(String id){ String key="Stu"+id; String name=""; //如果存在于Redis,就先从Redis里获取 if(slaveJedis.exists(key)){ //到从Redis服务器去找 System.out.println("ID: "+key+" exists in Redis."); name=slaveJedis.get(key);//找到后到从Redis里读 System.out.println("Name is: "+slaveJedis.get(key)); return name; }else{ //没在Redis,就到从MySQL去读 try{ slavePs=slaveConn.prepareStatement("select name from student where id=10"); ResultSet rs=slavePs.executeQuery(); if(rs.next()) { System.out.println("ID: "+key+" exists in Slave MySQL"); name=rs.getString("name"); System.out.println("Name is: "+name); //放入主Redis缓存 masterJedis.set(key,name); } return name; }catch (SQLException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } return name; } public static void main(String[] args) { MySQLClusterImprovedDemo tool=new MySQLClusterImprovedDemo(); tool.init(); tool.insertData(); //场景1 在主Redis中没有读到,则到从MySQL服务器中读 System.out.println(tool.getNameByID("10")); //场景2 当前ID=10已经存在于Redis,所以直接读缓存 System.out.println(tool.getNameByID("10")); } }
到此这篇关于Redis整合MySQL主从集群的示例代码的文章就介绍到这了,更多相关Redis整合MySQL主从集群内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论