redis三(3-1)

news2025/1/18 3:18:09

分布式缓存


基于Redis集群解决单机Redis存在的问题

 

单机的Redis存在四大问题

 

一、redis持久化

- RDB持久化
- AOF持久化

1.1RDB持久化

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。

快照文件称为RDB文件,默认是保存在当前运行目录。

Redis停机时会执行一次RDB。

1.执行时机--4种情况下

RDB持久化在四种情况下会执行:

- 执行save命令
- 执行bgsave命令
- Redis停机时
- 触发RDB条件时
1)save命令

执行下面的命令,可以立即执行一次RDB:



save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。



2)bgsave命令

下面的命令可以异步执行RDB:



这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。



3)停机时

Redis停机时会执行一次save命令,实现RDB持久化。



4)触发RDB条件

Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:


# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1  
save 300 10  
save 60 10000 

 

2.单机安装Redis

首先需要安装Redis所需要的依赖:

yum install -y gcc tcl

然后将下载好的Redis安装包上传到虚拟机的任意目录:

 

例如,我放到了/tmp目录:

 

解压缩:

tar -xzf redis-6.2.4.tar.gz

解压后:

 

 进入redis目录:

cd redis-6.2.4

运行编译命令:

make && make install

如果没有出错,应该就安装成功了。

然后修改redis.conf文件中的一些配置:

# 绑定地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问

bind 0.0.0.0

# 保护模式,关闭保护模式

protected-mode no

# 数据库数量,设置为1

databases 1

启动Redis:

redis-server redis.conf

停止redis服务:

redis-cli shutdown

Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

 

RDB的其它配置也可以在redis.conf文件中设置:

 

3.RDB原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

4.总结:

RDB方式bgsave的基本流程?

  • fork主进程得到一个子进程,共享内存空间
  • 子进程读取内存数据并写入新的RDB文件
  • 用新RDB文件替换旧的RDB文件。

RDB会在什么时候执行?save 60 1000代表什么含义?

  • 默认是服务停止时。
  • 代表60秒内至少执行1000次修改则触发RDB

RDB的缺点?

  • RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险
  • fork子进程、压缩、写出RDB文件都比较耗时

1.2AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

AOF的命令记录的频率也可以通过redis.conf文件来配:

 因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写

auto-aof-rewrite-percentage 100

# AOF文件体积最小多大以上才触发重写

auto-aof-rewrite-min-size 64mb

1.3RDB和AOF的差异

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

二、Redis主从

2.1搭建主从架构

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。

 Redis主从集群搭建:

2.1.我们搭建的主从集群结构如图:

 

共包含三个节点,一个主节点,两个从节点。

这里我们会在同一台虚拟机中开启3个redis实例,模拟主从集群,信息如下:

 

 2.2准备实例和配置

要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

1)创建目录

我们创建三个文件夹,名字分别叫7001、7002、7003:

# 进入/tmp目录

cd /tmp

# 创建目录

mkdir 7001 7002 7003

如图:

 

 2)恢复原始配置 修改redis-6.2.4/redis.conf文件,将其中的持久化模式改为默认的RDB模式,AOF保持关闭状态。

# 开启RDB

# save ""

save 3600 1

save 300 100

save 60 10000

# 关闭AOF

appendonly no

3)拷贝配置文件到每个实例目录

然后将redis-6.2.4/redis.conf文件拷贝到三个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝

cp redis-6.2.4/redis.conf 7001

cp redis-6.2.4/redis.conf 7002

cp redis-6.2.4/redis.conf 7003

# 方式二:管道组合命令,一键拷贝 echo 7001 7002 7003 | xargs -t -n 1 cp redis-6.2.4/redis.conf 4)修改每个实例的端口、工作目录

修改每个文件夹内的配置文件,将端口分别修改为7001、7002、7003,将rdb文件保存位置都修改为自己所在 目录(在/tmp目录执行下列命令):

sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf

sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf

sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf

5)修改每个实例的声明IP

虚拟机本身有多个IP,为了避免将来混乱,我们需要在redis.conf文件中指定每一个实例的绑定ip信息,格式如 下:

# redis实例的声明 IP

replica-announce-ip 192.168.150.101

每个目录都要改,我们一键完成修改(在/tmp目录执行下列命令):

# 逐一执行

sed -i '1a replica-announce-ip 192.168.150.101' 7001/redis.conf

sed -i '1a replica-announce-ip 192.168.150.101' 7002/redis.conf

sed -i '1a replica-announce-ip 192.168.150.101' 7003/redis.conf

# 或者一键修改

printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip 192.168.150.101' {}/redis.conf

2.3.启动

为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个

redis-server 7001/redis.conf

# 第2个

redis-server 7002/redis.conf

# 第3个

redis-server 7003/redis.conf

启动后:

 

如果要一键停止,可以运行下面命令:

printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-cli -p {} shutdown

2.4.开启主从关系

现在三个实例还没有任何关系,要配置主从可以使用replicaof 或者slaveof(5.0以前)命令。

有临时和永久两种模式:

修改配置文件(永久生效) 在redis.conf中添加一行配置:slaveof  <masterip> <masterport>

使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):

slaveof  <masterip> <masterport>

注意:在5.0以后新增命令replicaof,与salveof效果一致。

这里我们为了演示方便,使用方式二。

通过redis-cli命令连接7002,执行下面命令:

# 连接 7002

redis-cli -p 7002

# 执行slaveof

slaveof 192.168.150.101 7001

通过redis-cli命令连接7003,执行下面命令:

# 连接 7003

redis-cli -p 7003

# 执行slaveof

slaveof 192.168.150.101 7001

然后连接 7001节点,查看集群状态:

# 连接 7001

redis-cli -p 7001

# 查看状态

info replication

结果:

 

2.5.测试

执行下列操作以测试:

  • 利用redis-cli连接7001,执行set num 123
  • 利用redis-cli连接7002,执行get num,再执行set num 666
  • 利用redis-cli连接7003,执行get num,再执行set num 888

可以发现,只有在7001这个master节点上可以执行写操作,7002和7003这两个slave节点只能执行读操作。

 总结:

假设有A、B两个Redis实例,如何让B作为A的slave节点?

  • 在B节点执行命令:slaveof A的IP A的port

2.2主从数据同步原理

数据同步原理

主从第一次同步是全量同步:

master如何判断slave是不是第一次来同步数据?这里会用到两个很重要的概念:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。 因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据 

思考一下:

master如何判断slave节点是不是第一次来做数据同步?

主从第一次同步是全量同步

总结:

简述全量同步的流程?

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

主从第一次同步是全量同步

主从第一次同步是全量同步,但如果slave重启后同步,则执行增量同步

注意:

repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步。

可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

总结:

简述全量同步和增量同步区别?

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。
  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave

什么时候执行全量同步?

  • slave节点第一次连接master节点时 slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

思考:

slave节点宕机恢复后可以找master节点同步数据,那master节点宕机怎么办?

三、Redis哨兵

3.1哨兵的作用和原理

哨兵的作用

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

服务状态监控

 Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  • 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

选举新的master

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  • 最后是判断slave节点的运行id大小,越小优先级越高。

如何实现故障转移

当选中了其中一个slave为新的master后(例如slave1),故障的转移的步骤如下:

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

 总结:

Sentinel的三个作用是什么?

  • 监控
  • 故障转移
  • 通知

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点,执行slaveof 新master

3.2搭建哨兵集群

1.集群结构

 这里我们搭建一个三节点形成的Sentinel集群,来监管之前的Redis主从集群。如图:

 

三个sentinel实例信息如下:

2.准备实例和配置

要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

我们创建三个文件夹,名字分别叫s1、s2、s3:

# 进入/tmp目录

cd /tmp

# 创建目录

mkdir s1 s2 s3

如图:

 

然后我们在s1目录创建一个sentinel.conf文件,添加下面的内容:

port 27001

sentinel announce-ip 192.168.150.101

sentinel monitor mymaster 192.168.150.101 7001 2

sentinel down-after-milliseconds mymaster 5000

sentinel failover-timeout mymaster 60000

dir "/tmp/s1"

解读:

  • port 27001:是当前sentinel实例的端口
  • sentinel monitor mymaster 192.168.150.101 7001 2:指定主节点信息

mymaster:主节点名称,自定义,任意写

192.168.150.101 7001:主节点的ip和端口

2:选举master时的quorum值

然后将s1/sentinel.conf文件拷贝到s2、s3两个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝

cp s1/sentinel.conf s2

cp s1/sentinel.conf s3

# 方式二:管道组合命令,一键拷贝

echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf

修改s2、s3两个文件夹内的配置文件,将端口分别修改为27002、27003:

sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf

sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf

3.3.启动 Redis集群

 为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个

redis-sentinel s1/sentinel.conf

# 第2个

redis-sentinel s2/sentinel.conf

# 第3个

redis-sentinel s3/sentinel.conf

启动后:

 

3.4.测试

尝试让master节点7001宕机,查看sentinel日志:

 

查看7003的日志:

 

查看7002的日志:

 

3.3RedisTemplate的哨兵模式

RedisTemplate的哨兵模式

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

首先,我们引入课前资料提供的Demo工程:

 

1.在pom文件中引入redis的starter依赖:

2.然后在配置文件application.yml中指定sentinel相关信息:

3.配置主从读写分离

这里的ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave(replica)节点读取
  • REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

四、Redis分片集群

4.1搭建分片集群

分片集群结构

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题
  • 高并发写的问题

使用分片集群可以解决上述问题,分片集群特征:

  • 集群中有多个master,每个master保存不同数据
  • 每个master都可以有多个slave节点
  • master之间通过ping监测彼此健康状态
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

1.集群结构

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个 slave节点,结构如下:

 

 这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:

 

2.准备实例和配置

删除之前的7001、7002、7003这几个目录,重新创建出7001、7002、7003、8001、8002、8003目录:

 # 进入/tmp目录

cd /tmp

# 删除旧的,避免配置干扰

rm -rf 7001 7002 7003

# 创建目录

mkdir 7001 7002 7003 8001 8002 8003

在/tmp下准备一个新的redis.conf文件,内容如下:

port 6379

# 开启集群功能

cluster-enabled yes

# 集群的配置文件名称,不需要我们创建,由redis自己维护

cluster-config-file /tmp/6379/nodes.conf

# 节点心跳失败的超时时间

cluster-node-timeout 5000

# 持久化文件存放目录

dir /tmp/6379

# 绑定地址

bind 0.0.0.0

# 让redis后台运行

daemonize yes

# 注册的实例

ip replica-announce-ip 192.168.150.101

# 保护模式

protected-mode no

# 数据库数量

databases 1

# 日志

logfile /tmp/6379/run.log

将这个文件拷贝到每个目录下:

# 进入/tmp目录

cd /tmp

# 执行拷贝

echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

修改每个目录下的redis.conf,将其中的6379修改为与所在目录一致:

# 进入/tmp目录

cd /tmp

# 修改配置文件

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf Redis

4.3.启动

因为已经配置了后台启动模式,所以可以直接启动服务:

# 进入/tmp目录

cd /tmp

# 一键启动所有服务

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf

通过ps查看状态:

ps -ef | grep redis

发现服务都已经正常启动:

 

如果要关闭所有进程,可以执行命令:

ps -ef | grep redis | awk '{print $2}' | xargs kill

或者(推荐这种方式):

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown

4.4.创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。

我们需要执行命令来创建集群,在Redis5.0之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli 中。

1)Redis5.0之前 Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。因为redis-trib.rb是有ruby语言编写的 所以需要安装ruby环境。

# 安装依赖

yum -y install zlib ruby rubygems

gem install redis

然后通过命令来管理集群:

# 进入redis的src目录

cd /tmp/redis-6.2.4/src

# 创建集群

./redis-trib.rb create --replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002

192.168.150.101:8003

2)Redis5.0以后

我们使用的是Redis6.2.4版本,集群管理以及集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001

192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001

192.168.150.101:8002 192.168.150.101:8003

命令说明:

redis-cli --cluster或者./redis-trib.rb:代表集群操作命令

create:代表是创建集群

--replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave 节点,随机分配到不同master

运行后的样子:

 

 这里输入yes,则集群开始创建:

 

通过命令可以查看集群状态:

redis-cli -p 7001 cluster nodes

 

4.5.测试

尝试连接7001节点,存储一个数据:

# 连接

redis-cli -p 7001

# 存储数据

set num 123

 # 读取数据

get num

# 再次存储

set a 1

结果悲剧了:

 

集群操作时,需要给redis-cli加上-c参数才可以:

redis-cli -c -p 7001  

这次可以了:

4.2散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  • key中不包含“{}”,整个key都是有效部分

例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

 总结:

Redis如何判断某个key应该在哪个实例?

  • 将16384个插槽分配到不同的实例
  • 根据key的有效部分计算哈希值,对16384取余
  • 余数作为插槽,寻找插槽所在实例即可

如何将同一类数据固定的保存在同一个Redis实例?

  • 这一类数据使用相同的有效部分,例如key都以{typeId}为前缀

4.3集群伸缩

添加一个节点到集群

redis-cli --cluster提供了很多操作集群的命令,可以通过下面方式查看:

比如,添加节点的命令:

 案例:向集群中添加一个新的master节点,并向其中存储 num = 10

需求:

  • 启动一个新的redis实例,端口为7004
  • 添加7004到之前的集群,并作为一个master节点
  • 给7004节点分配插槽,使得num这个key可以存储到7004实例

练习:删除集群中的一个节点

需求:

  • 删除7004这个实例

4.4故障转移

当集群中有一个master宕机会发生什么呢?

1.首先是该实例与其它实例失去连接

2.然后是疑似宕机:

3.最后是确定下线,自动提升一个slave为新的master:

 数据迁移

利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:

手动的Failover支持三种不同模式:

  • 缺省:默认的流程,如图1~6歩
  • force:省略了对offset的一致性校验
  • takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见

 案例:在7002这个slave节点执行手动故障转移,重新夺回master地位

步骤如下:

1.利用redis-cli连接7002这个节点

2.执行cluster failover命令

4.5RedisTemplate访问分片集群

RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致: 1.引入redis的starter依赖

2.配置分片集群地址

3.配置读写分离

与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下:

 思考:

Redis的分片集群、Elasticsearch的分片集群有哪些共同的特征呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java项目-第150期ssm网络视频播放器-java毕业设计_计算机毕业设计

java项目-第150期ssm网络视频播放器-java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm网络视频播放器》 该项目分为2个角色&#xff0c;管理员、用户。 用户可以浏览前台查看视频信息、系统公告、论坛信息。 并且可以进入到个人中心查看视频信息、…

计算机毕业设计java基于javaweb+ssm+vue婚纱摄影网站

本站不同于其它摄影网站&#xff0c;本网站不但可以展示本店的摄影作品&#xff0c;更可以列出众多摄影套餐供用户选择预约&#xff0c;用户看中哪款套餐了&#xff0c;可以预约时间进行拍摄&#xff0c;即增加了店内本身的业务量&#xff0c;也方便了客户直接在线订套餐。 对于…

[附源码]计算机毕业设计JAVA基于JAVAWEB的高校实训管理系统

[附源码]计算机毕业设计JAVA基于JAVAWEB的高校实训管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a;…

nacos源码分析-服务注册(客户端)

前言 一直都想写SpringCloudAlibaba的源码分析&#xff0c;终于开始动手第一篇了&#xff0c;如果想要看懂Nacos源码至少要把《SpringBoot自动》配置看了&#xff0c;不然就是看天书。本篇文章呢带大家一起来看一下Nacos-Client 客户端服务注册这一部分的源码。 基础环境 首…

MongoDB基本查询语句

文章目录 查询选择器查询就是获取存储在数据库中的数据。在MongoDB中,查询通常针对一个集合来操作。查询可以指定查询条件,只返回匹配的文档;还可以指定投影项,只返回指定的字段,减少返回数据到客户端的网络流量。 为了进行测试,我们先假想一个常用的电子商务网站上可能用…

svg VS canvas,哪种在移动端适配度更好?实战经历告诉你~

最近做了一个画图的功能,后端提供棋盘数据,前端需要把数据转换成一个棋盘画出来,当时有两种实现方法,一种是使用canvas画图,一个是使用svg画图. ui提供的设计稿如下: 由于这是一个轮播图,当后端返回多少张棋盘数据时,就需要渲染多少张棋盘,最多有十张,基于canvas和svg画图,为了…

【Milvus的以图搜图】

0. 介绍 Milvus官方在bootcamp项目中给开发者提供多种解决方案&#xff0c;包含常见的以图搜图、人脸检索、DNA相似性检索、视频检索等等&#xff0c;具体可以参考bootcamp项目。 本文主要就bootcamp中以图搜图reverse_image_search的代码介绍如何运行该样例&#xff0c;进而了…

文献阅读-VSE++:使用困难负样本来改经视觉语义嵌入

Title&#xff1a;《VSE: Improving Visual-Semantic Embeddings with Hard Negatives》 Authors&#xff1a;Fartash FaghriDavid FleetJ. KirosS. FidlerJournal&#xff1a;ArXiv (2017)Date&#xff1a;2017 code&#xff1a;GitHub - fartashf/vsepp: PyTorch Code for t…

Java基础38 面向对象三大特征之多态

OOP之多态 多态1.多态的具体体现2.向上转型3.向下转型4.属性重写5.instanceOf6.动态绑定机制&#xff08;核心&#xff09;● Java的动态访问机制7.多态数组8.多态参数)多态 ● 多【多种】态【状态】 方法或对象具有多种形态。 是建立在封装和继承之上的面向对象的第三大特征…

一文带你学会Vue3基本语法

Vue3 起步1.通过 CDN 使用 Vue32.Vue3 模板语法文本Html属性表达式指令参数3.模板用户输入双向绑定1.通过 CDN 使用 Vue3 你可以借助 script 标签直接通过 CDN 来使用 Vue&#xff1a; <script src"https://unpkg.com/vuenext"></script>通过 CDN 使用…

在WPF中使用Prism弹出自定义窗体样式的对话框

概述 我们在Prism中弹出一个对话框&#xff0c;默认是一个Windows默认样式的窗口&#xff0c;这样会同自己所开发的项目完全不搭调&#xff0c;譬如下面这样子 那么如果为了配合软件主体的风格&#xff0c;可以做出类似这样效果 其实原理也很简单&#xff0c;Prism也考虑到了这…

不科学,RocketMQ生产者在一个应用服务竟然不能向多个NameServer发送消息

前言 目前有两套RocketMQ集群&#xff0c;集群A包含topic名称为cluster_A_topic&#xff0c;集群B包含topic名称为cluster_B_topic&#xff0c;在应用服务OrderApp上通过RocketMQ Client创建两个DefaultMQProducer实例发送消息给集群A和集群B&#xff0c;架构图如下&#xff1…

使用Vue脚手架配置代理服务器的两种方式

1 前言 本文主要介绍使用Vue脚手架配置代理服务器的两种方式 注意&#xff1a;Vue脚手架给我们提供了两种配置代理服务器的方式&#xff0c;各有千秋&#xff0c;使用的时候只能二选一&#xff0c;不能同时使用 2 代理 除了cros和jsonp&#xff0c;还有一种代理方式&#x…

传奇GM调整极品属性的命令------技术分享

传奇GM调整极品属性的命令 GM命令supermake命令用法&#xff01; 以下格式皆为supermake a b c   以上命令含义&#xff1a;调整A(装备)的B(属性)到C(点数) supermake 1 0 10  1代表武器  0代表攻击 10代表调整的点数 B参数代表需要调整的那项属性如攻击 魔法 道术 …

黑*头条_第4章_文章搜索前后端成形记 实名认证审核

黑*头条_第4章_文章搜索前后端成形记 & 实名认证审核 文章目录黑*头条_第4章_文章搜索前后端成形记 & 实名认证审核文章搜索前后端成形记 & admin实名认证审核1 文章详情-前端开发1.1登录接口1.1.1 基本定义1.1.2 code定义1.1.3 mapper实现1.1.4 service代码实现1.…

宝塔一键安装wordpress

使用宝塔面板来部署网站是非常方便的&#xff0c;以WordPress网站为例来说&#xff1a; 一般有两种方式安装WordPress网站&#xff0c;第一种是上传网站程序到网站根目录手动安装&#xff0c;另外一种是在宝塔面板后台左侧菜单&#xff0c;找到“WordPress一键部署”&#xff…

Map 和 Set

模型 一般我们把搜索的数据称为 关键字(key) , 关键字对应的值叫做 值(value) , 将之称为 key-value 键值对. 衍生出两种模型: 1. 纯 key 模型 例如 : 班级上点名, 在花名册上找人的名字. 2. key-value 模型 例如 : 统计一个字符串中每个字母出现的次数, 结果是每个字母和它对…

简易版 图书管理系统

目录 1. Book包 1.1 Book类 1.2 BookList类 2. User包 2.1 User抽象类 2.2 AdminUser类 2.3 NormalUser类 3. Operate包 3.1 MyOperate接口 3.2 AddOperation类 3.3 DelOperation类 3.4 ExitOperation 3.5 FindOperation类 3.6 ShowOperation类 3.7 BorrowedOpe…

MySQL——数据库、表的操作

文章目录数据库的操作创建数据库创建数据库例子字符集和校验规则查看数据库支持的字符集查看默认的字符校验规则校验规则对数据库的影响查看数据库显示详细的创建数据库语句修改数据库删除数据库查看连接情况表的操作创建表显示创建表的详细过程不同的数据库引擎查看表结构修改…

【C语言】操作符与优先级详解

C的操作符 文章目录C的操作符前言一、算术操作符二、移位操作符三、位操作符四、赋值操作符五、单目操作符六、条件操作符七、逻辑操作符八、条件操作符九、逗号表达式十、下标引用、函数调用和结构成员十一、表达式求值11.1 隐式类型转换12.2 算术转换12.2 操作符的属性总结前…