1. 20230612学习记录
目标
- docker mysql容器数据持久化
- mysql主从配置
- redis安装
- 了解redis基本类型和命令
- redis简单应用
文章目录
1.1. docker中的mysql数据持久化
1.1.1. 在宿主机创建data、conf两个目录
#进入/usr/local/software
cd /usr/local/software
#在software下创建/mysql/3306目录,用于存放3306这个数据库服务的内容
mkdir -p mysql/3306
#在3306目录下创建data、conf
mkdir data
mkdir conf
1.1.2. 在conf目录下拷贝一个my.cnf
将配置文件拷贝到刚刚创建的conf目录下
#可以从容器中拷贝出来
docker cp mysql_3306:/etc/my.cnf ./
#mysql_3306容器名称
#/etc/my.cnf 源路径 容器中my.cnf文件的路径
#./ 目的路径 宿主机路径 当前我们在conf目录下,所以直接使用./ 代表当前目录
拷贝的有问题,可以新建一个
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# The MySQL Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
default_authentication_plugin=mysql_native_password
# Custom config should go here
!includedir /etc/mysql/conf.d/
1.1.3. 持久化设置
重新创建容器,用数据卷挂载的方式将mysql的数据(映射数据目录)持久化到宿主机
如果原来有创建了对应的mysql容器需先删除原来的
docker run -itd --name mysql_3306 --privileged=true -p 3306:3306 -v /usr/local/software/mysql/3306/data:/var/lib/mysql -v /usr/local/software/mysql/3306/conf/my.cnf:/etc/mysql/my.cnf -v /usr/local/software/mysql/3306/mysql-files:/var/lib/mysql-files -e MYSQL_ROOT_PASSWORD=99120805 mysql
-v 宿主机目录:容器目录
挂载的数据卷不会随着容器的删除而删除,达到持久化的效果
1.2. mysql主从设置
1.2.1. 原理
MySQL 主从复制是基于从服务器读取主服务器的二进制日志跟踪所有对数据库的更改
从库
生成两个线程,一个 I/O 线程,一个 SQL 线程;- I/O 线程去请求
主库
的 binlog,并将得到的 binlog 日志写到 relay log(中继日志) 文件中; 主库
会生成一个 log dump 线程,用来给从库
I/O 线程传 binlog;从库
的SQL 线程会读取 relay log 文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;
参考:https://ost.51cto.com/posts/11721
1.2.2. 修改主mysql
的my.cnf配置文件
#服务id
server-id=200
log-bin=mysql-bin
binlog_format=row
1.2.3. 主mysql
创建mysql从账号并配置权限
- 创建从账号
# create user '用户名'@'主机名' identified by '密码'; % 任何主机
create user 'slave'@'%' identified by '99120805';
- 授予权限
#*.* 所有数据库的所有数据表
grant replication slave, replication client on *.* to 'slave'@'%';
- 修改密码
#8.0mysql的加密方式改变,肯l修改一下密码
alter user 'slave'@'%' identified with mysql_native_password by '99120805';
- 生效配置
flush privileges;
1.2.4. 创建第二个数据库容器作从mysql
宿主机创建新的目录(3310)作挂载,作持久化处理
使用宿主机端口3310映射容器3306端口,创建容器
docker run -itd --name mysql_3310 --privileged=true -p 3310:3306 -v /usr/local/software/mysql/3310/data:/var/lib/mysql -v /usr/local/software/mysql/3310/conf/my.cnf:/etc/mysql/my.cnf -v /usr/local/software/mysql/3310/mysql-files:/var/lib/mysql-files -e MYSQL_ROOT_PASSWORD=99120805 mysql
修改从mysql的my.cnf
server-id=201
log-bin=mysql-slave-01-bin
relay_log=edu-mysql-relay-bin
read-only=1
1.2.5. 从mysql
中配置主服务器配置
-
先在
主mysql
中查询master状态show master status
file和position的值在
从mysql
中设置主从配置需要用到
-
进入
从mysql
配置主服务器配置设置从的主服务器主机为
172.17.0.2
(主mysql的容器id),主服务器用户为slave
(主mysql创建的从账户),主服务器用户密码99120805
(主mysql创建的账户密码),MASTER_LOG_FILE(主mysql查询的master状态 file),MASTER_LOG_PO(主mysql查询的master状态 position)change master to master_host='172.17.0.2',master_user='slave',master_password='99120805',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1132;
-
验证是否成功
show slave status \G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
这两个状态为Yes,一般成功了
在主mysql中创建一个表,若从mysql自动创建了一张表,即配置成功。
1.3. redis
1.3.1. 简介
基于内存的KV
存储系统,是跨平台的非关系型数据库,通常被称为数据结构服务器。
1.3.2. docker安装redis
1.3.2.1. 搜寻镜像
docker search redis
1.3.2.2. 拉取镜像
docker pull redis
1.3.2.3. 创建容器
docker run -itd --name=redis_6379 -p 6379:6379 redis
1.3.2.4. 进入redis容器
docker exec -it redis_6379 bash
1.3.2.5. 进入redis
redis-cli
成功进入后输入ping 响应PONG表示resdis安装成功
root@6ddb8ceaa3ce:/data# redis-cli
127.0.0.1:6379> ping
PONG
1.3.3. redis基本数据类型
1.3.3.1. 字符串(string)
基本命令
命令 | 描述 |
---|---|
set key value | 设置指定 key 的值,一个key只能存一个value,继续使用覆盖原值 |
get key | 获取指定 key 的值。 |
mget key1 key2 … keyn | 获取所有(一个或多个)给定 key 的值。 |
setnx key value | 只有在 key 不存在时设置 key 的值。 |
strlen key | 返回 key 所储存的字符串值的长度。 |
incr key | 将 key 中储存的数字值(存储的字符串为数字值)增一。 |
decr key | 将 key 中储存的数字值(存储的字符串为数字值)减一。 |
1.3.3.2. 列表(list)
value值是一个队列,命令分左右(头尾)插入数据
命令 | 描述 |
---|---|
llen key | 获取列表长度 |
lpush key value1… value2 | 将一个或多个值插入到列表头部 获取时value2在value1前面 |
lpop key | 移出并获取列表的第一个元素 |
lrange key start stop | 获取列表指定范围内的元素 起始为0 |
lrem key count value | 移除列表指定数量的指定元素。 conunt指定删除个数 可以为正数,负数,0;为正数时 ,按从头到尾的顺序删除指定个数元素,为负数时 ,从尾到头的删除指定个数元素,为0时 ,删除所有指定元素 |
rpush key value1… value2 | 尾部添加 |
rpop key [count] | 尾部移除[count]元素 |
1.3.3.3. 集合(set)
无序,不重复
命令 | 描述 |
---|---|
sadd key member1… member2 | 向集合添加一个或多个成员 |
scard key | 获取集合的成员数 |
smembers key | 返回集合中的所有成员 |
sismember key member | 判断member元素是否是集合key的成员 |
spop key | 移除并返回集合中的一个随机元素 |
1.3.3.4. 有序集合(sorted set)
有序,不重复
命令 | 描述 |
---|---|
zadd key score1 member1… score2 member2 | 向有序集合添加一个或多个成员,或者更新已存在成员的score;score代表排序的权重 |
zcard key | 获取集合的成员数 |
zcount key min max | 计算在有序集合中指定区间分数的成员数 |
zrangebylex key min max[limit offset count] | 通过字典区间返回有序集合的成员 |
zrem key member1 member2 | 移除有序集合中的一个或多个成员 |
ZREMRANGEBYSCORE key min max | 移除有序集合中给定的分数区间的所有成员 |
zscore key member | 返回有序集中,成员的分数值 |
1.3.3.5. hash
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
命令 | 描述 |
---|---|
hdel key field1 field2… fieldn | 删除一个或多个哈希表字段 |
hexists key field | 查看哈希表 key 中,指定的字段是否存在 |
hget key field | 获取存储在哈希表中指定字段的值 |
hgetall key | 获取在哈希表中指定 key 的所有字段和值 |
hincrby key field increment | 为哈希表 key 中的指定字段的整数值加上增量 increment |
hkeys key | 获取所有哈希表中的字段(field) |
hlen key | 获取哈希表中字段的数量 |
hmget key field1 field2 | 获取所有给定字段的值 |
hset key field value | 在哈希表 key 中设置字段 field value 映射。为了易于阅读 field和value 使用key:field key:value的形式 |
hsetnx key field value | 只有在字段 field 不存在时,设置哈希表字段的值。 |
hvals key | 获取哈希表中所有值 |
1.3.4. 常用命令
命令 | 描述 |
---|---|
del key | 删除 key。 del [key…] 可以一次删除多个key |
exists key | 检查给定 key 是否存在。 exists [key…] |
expire key seconds | 为给定 key 设置过期时间 以秒为计 。 expire [key] 10 设定10秒 |
pexpire key millisenconds | 为给定 key 设置过期时间 以毫秒计 。 pexpire [key] 100 设定100毫秒 |
keys pattern | 查找所有符合给定表达式(pattern)的 key 。 keys * :查找所有key keys a?? :查找开头三位的key |
ttl key | 以秒 为单位,返回给定 key 的剩余生存时间(TTL, time to live)。 key不存在返回-2;key存在但没有过期时间返回-1。 |
type key | 返回 key 所储存的值的类型。 |
1.3.5. redis 、mysql性能
1.3.6. springboot使用redis
1.3.6.1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1.3.6.2. 使用spring提供的StringRedisTemplate类
-
Redis的String类型存取操作
stringRedisTemplate.opsForValue().get(key) stringRedisTemplate.opsForValue().set(key,value)
1.3.7. 应用:验证码存取
如何确定提交的验证码的来源
创建验证码时使用唯一的标识,用于存验证码的key,key还需要给到客户端,用于提交验证码时的取;
此处标识的创建使用UUID
;标识的传递使用cookie
1.3.7.1. 验证码图片生成器
Hutool是一个小而全的Java工具类库
https://hutool.cn/docs/#/captcha/%E6%A6%82%E8%BF%B0
hutool-captcha是其中的图形形验证码工具包
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.18</version>
</dependency>
-
LineCaptcha 线段干扰的验证码
//定义图形验证码的长、宽、验证码字符数、干扰线段长度 LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100,50,4,100); //创建验证码 lineCaptcha.createCode(); //获取验证码的文本内容 lineCaptcha.getCode(); //将验证码写出到目标流中 lineCaptcha.write(response.getOutputStream());
-
CircleCaptcha 圆圈干扰验证码
//定义图形验证码的长、宽、验证码字符数、干扰圆圈个数 CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
-
ShearCaptcha 扭曲干扰验证码
//定义图形验证码的长、宽、验证码字符数、干扰线宽度 ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);
1.3.7.2. 代码实现
@RestController()
@RequestMapping("/api/user")
public class CodeController {
@Autowired
private StringRedisTemplate redisTemplate;
private static LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100,50,4,100);
@GetMapping("/getCode")
public void getCode(HttpServletResponse response){
//创建线段干扰图形验证码
lineCaptcha.createCode();
//获取图形验证码文本内容
String code = lineCaptcha.getCode();
//使用UUID作为存入redis的key
String codeKey = UUID.randomUUID().toString();
//存入redis,设置过期时间60s
redisTemplate.opsForValue().set(codeKey,code,60, TimeUnit.SECONDS);
//创建key的cookie
Cookie cookie = new Cookie("cc",codeKey);
response.addCookie(cookie);
//将图形验证码写出到response
try {
lineCaptcha.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@GetMapping("/check")
public String check(String code, HttpServletRequest request){
for (Cookie cookie : request.getCookies()) {
if(cookie.getName().equals("cc")){
String realCode = redisTemplate.opsForValue().get(cookie.getValue());
if(null==realCode){
return "验证码不存在";
}
if(!realCode.equals(code)){
return "验证码错误";
}
return "验证成功";
}
}
return "验证码不存在";
}
}