学习技术是枯燥的,更是有趣和满心欢喜的。
1,前言
首先为什么【高】加了双引号?
因为我没有多节点(3个以上)或者上云测试过,也没有部署前端Nginx+Tomcat集群,算不上真正完整的能抗住高并发的系统,文章内容只给大家提供一个基本实现和部署细节,大家可以指摘出其中的问题,或有更好的建议意见也欢迎告诉我。
2,CentOS部署Redis主从集群
概要:5个CentOS虚拟机节点,分别部署在两台物理主机的虚拟机上。
IP地址为:192.168.2.5/192.168.2.6/192.168.2.8/192.168.2.9/192.168.2.10/192.168.2.11
2.1,安装CentOS的问题
过程可以百度,分享一下安装完成后的一些问题。
Q:安装完成后不可以上网的原因?
A:是因为没有配置
IP
地址,Centos
默认是以DHCP
方式上网,我们通过修改/etc/sysconfig/network-scripts/ifcfg-ens33
文件中的onboot=yes
,并且改变该虚拟机的网络连接方式为桥接模式
。设定完成后在root
用户下,用 ***service network restart***命令重启网络服务后即可上网了。
配置网络yum源:
# 1.备份原始yum源:
cd /etc/yum.repos.d
mv CentOS-Base.repo CentOS-Base.repo.bak
# 2.配置CentOS的DNS:
vim /etc/resolv.conf
nameserver 114.114.114.114 # 国内dns
nameserver 8.8.8.8 # 国外dns
# 3.下载yum文件替代原始yum源:
# (1)网易yum源:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum clean all # 清除缓存
yumakecache # 生成缓存
解析:wget -o,使用“-o”参数来指定一个文件名
# (2)阿里云yum源:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all
yum makecache
Centos 7之后,无法使用
iptables
控制Linux的端口原因:Centos 7使用
firewalld
代替了原来的iptables
。
(1)、firewalld的基本使用
启动: systemctl start firewalld
关闭: systemctl stop firewalld
查看状态: systemctl status firewalld
开机禁用 : systemctl disable firewalld
开机启用 : systemctl enable firewalld
(2)、systemctl是CentOS7的服务管理工具中主要的工具,它融合之前service和chkconfig的功能于一体。
启动一个服务:systemctl start firewalld.service
关闭一个服务:systemctl stop firewalld.service
重启一个服务:systemctl restart firewalld.service
显示一个服务的状态:systemctl status firewalld.service
在开机时启用一个服务:systemctl enable firewalld.service
在开机时禁用一个服务:systemctl disable firewalld.service
查看服务是否开机启动:systemctl is-enabled firewalld.service
查看已启动的服务列表:systemctl list-unit-files|grep enabled
查看启动失败的服务列表:systemctl --failed
# 1.先查看防火墙状态
firewall-cmd --state
# 2.停止防火墙
systemctl stop firewalld.service
# 3.禁止firewall开机启动
systemctl disable firewalld.service
# 防火墙的基本使用
# CentOS7使用firewalld打开关闭防火墙与端口
# 1、firewalld的基本使用
启动: systemctl start firewalld
关闭: systemctl stop firewalld
查看状态: systemctl status firewalld
开机禁用 : systemctl disable firewalld
开机启用 : systemctl enable firewalld
(3)、配置firewalld-cmd
查看版本: firewall-cmd --version
查看帮助: firewall-cmd --help
显示状态: firewall-cmd --state
查看所有打开的端口: firewall-cmd --zone=public --list-ports
更新防火墙规则: firewall-cmd --reload
查看区域信息: firewall-cmd --get-active-zones
查看指定接口所属区域: firewall-cmd --get-zone-of-interface=eth0
拒绝所有包:firewall-cmd --panic-on
取消拒绝状态: firewall-cmd --panic-off
查看是否拒绝: firewall-cmd --query-panic
2.2,安装JDK
(1),首先我们需要下载Linux版本的JDK。
(2),将下载好的jdkxxx-xx.tar.gz
包拷贝到Linux系统桌面。
(3),用 cp jdkxxx-xx.tar.gz /opt
拷贝至 /opt
路径下,用tar -xzvf jdkxxx-xx.tar.gz
解压。
(4),用 vim /etc/profile
命令添加JDK配置信息:
export JAVA_HOME="/opt/jdkxxx-xx"
export PATH="$JAVA_HOME/bin:$PATH"
(5),用 source /etc/profile :wq
命令刷新一下上述的修改配置。
(6),用 echo $JAVA_HOME
命令可以查看JDK版本信息。
2.3,安装Redis集群
2.3.1,Redis单机安装
(1),首先需要下载Linux版的Redis,用cp redis-x.x.x.tar.gz /usr/local
命令拷贝至 /usr/local
路径下,用tar -xzvf redis-x.x.x.tar.gz
解压。解压之后会生成名为 redis-x.x.x
的文件夹。
(4),安装C语言环境【redis是用c语言开发的,所以需要该环境】
yum install gcc-c++
(5),进入redis-x.x.x
的文件夹使用 make 命令编译Redis源码
make
(6),安装Redis到指定的目录
make install PREFIX=/usr/local/redis # 如果不指定PREFIX参数的话,会默认安装到当前路径下
(7),安装完成后会在 /usr/local/redis
下生成一个 bin 文件夹【如果没有生成的话,可以使用 make test命令查看一下是否缺少依赖包,一般这里会缺少 tcl 包,我们只需用 yum install tcl
安装一下就可以了】
(8),从 redis的解压缩目录下拷贝 redis.conf
配置文件到安装目录 /usr/local/redis/bin
里。【一个redis需要一个redis.conf
,多个redis的话就需要多个redis.conf
配置文件】;其中默认IP地址:127.0.0.1
,默认端口号:6379
【默认端口号】。
配置文件的地址需要改成redis的服务器IP地址
bind 127.0.0.1【只能自己本地访问redis,一般设定成本机的IP地址】
(9),启动redis:在redis 安装目录用下面命令启动redis,需要指定配置文件才能启动哦
./redis-server ./redis.conf
#如果仅仅使用./redis-server的话就属于前端启动,
(10),关闭redis:
./redis-cli -h 主机IP地址 -p 6379(默认端口号) shutdown
2.3.2,Redis集群安装
(1),配置(或升级)ruby
# 在centos7中默认ruby是2.0.0版本,低于redis4.0.6最低的最低要求的2.2版本,所以需要进行升级。
# 办法是将自带的ruby卸载,在安装可以支持redis的版本。
# 卸载ruby
$ yum remove ruby
# 下载
$ wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.0.tar.gz
# 解压
$ tar -zxvf ruby-2.5.0.tar.gz
# 进入目录
$ cd ruby-2.5.0
#创建安装目录
$ mkdir -p /usr/local/ruby
# 配置并制定安装位置
$ ./configure --prefix=/usr/local/ruby
# 编译与安装,这个过程很慢,你可以去腾云驾雾一下
$ make && make install
# 建立软链接
使用命令ln -s 文件所在位置 目的位置
命令这么写。(ln -s /usr/local/ruby/bin/ruby /usr/local/bin/ruby)
是LN 不是in
# 查看ruby版本
$ ruby -v
(2),配置Redis和ruby接口
$ yum install rubygems
# redis与ruby的接口
$ gem install redis
(3),部署其余五个节点的Redis,对各节点Redis的配置文件==redis.conf
==做如下修改
bind 本机IP地址
# 设置为 redis后台运行(守护进程)
daemonize yes
# 开启aof数据备份
appendonly yes
# 开启集群
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
(4),随便选一台Redis,进入redis-5.0.x
目录【Redis解压缩目录】下,开启集群
# 回到Redis安装完成的目录下
./src/redis-trib.rb create --replicas 1 192.168.2.5:6379 192.168.2.6:6379 192.168.2.8:6379 192.168.2.9:6379 192.168.2.10:6379 192.168.2.11:6379
# 或者回到Redis安装完成的目录下按照以下命令启动集群
./bin/redis-cli --cluster create 192.168.2.5:6379 192.168.2.6:6379 192.168.2.8:6379 192.168.2.9:6379 192.168.2.10:6379 192.168.2.11:6379 --cluster-replicas 1
(5),分别启动各个节点的Redis服务【可以写个shell脚本实现】,至此,Redis集群的部署全部完成。
3,SpringBoot实现扣库存的核心代码
废话不多说,直接上核心代码吧
pom.xml中添加以下配置,reids的starter包和目前最成熟的redis操作集合redisson
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.0</version>
</dependency>
添加Redisson的配置类,使其能被Spring容器注入进来
@Configuration
public class RedissonConfig {
@Bean
public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
return new RedissonConnectionFactory(redisson);
}
@Bean
public RedissonClient redissonClient() throws IOException {
/**
* Java 代码配置
*/
Config config = new Config();
/**
* 192.168.2.5[master] ---- 192.168.2.10[slave]
* 192.168.2.6[master] ---- 192.168.2.11[slave]
* 192.168.2.8[master] ---- 192.168.2.9[slave]
*/
config.useClusterServers()
.addNodeAddress("redis://192.168.2.5:6379",
"redis://192.168.2.6:6379",
"redis://192.168.2.8:6379",
"redis://192.168.2.9:6379",
"redis://192.168.2.10:6379",
"redis://192.168.2.11:6379");
return Redisson.create(config);
}
}
Controller中通过redisson实现分布式锁的方式扣减Redis中的库存
@PatchMapping("/delete")
public void deleteById(){
final String KEY_NUMS = "nums";
String lockKey = "cy";
boolean flg = false;
// 通过redisson自带的RedLock方式实现分布式锁
// RedLock的lock和unlock是通过Lua脚本实现获得和释放锁的,Lua能保证操作的原子性。【大家可以搜搜看,实现起来还是比较简单】
RLock lock = redissonClient.getLock(lockKey);
try{
// 加锁
flg = lock.tryLock(1000, TimeUnit.MILLISECONDS);
if(flg) {
int count = Integer.parseInt(stringRedisTemplate.opsForValue().get(KEY_NUMS));
if (count > 0) {
int realCount = count - 1;
stringRedisTemplate.opsForValue().set(KEY_NUMS, realCount + "");
System.out.println("==减库存【成功】,剩余库存为: " + realCount+" ==");
} else {
System.out.println("==减库存【失败】,库存不足!==");
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(flg) {
lock.unlock();
}
}
}
4,Jmeter并发测试结果
一共20000次请求,吞吐量为12620次/分钟,错误比较多,大概是有很多次接口连不上,原因可能是请求一下子太多Tomcat服务器处理不了,拒绝了很多请求连接。