- 1、SpringBoot
- 2、分布式
- 3、Ngnix
- http://localhost:8091;
}
}">server代表一个服务项
server {
listen 80; #监听端口
#server_name 表示拦截域名
server_name localhost;
#拦截请求之后处理方式
location / {
#root 是关键字 代表反向代理的文件夹名称
root html;
#index 默认跳转页面
index index.html index.htm;
}
}
如配置图片代理,并修改hosts文件
#配置图片服务器
server {
listen 80;
server_name image.jt.com;
location / {
root D:/1-jt/image;
}
}
实现域名代理
#后台管理服务器 用户访问manage.jt.com时访问localhost:8091
server {
listen 80;
server_name manage.jt.com;
location / {
#代理路径
proxy_pass http://localhost:8091;
}
} - http://jt-windows;
#链接服务器超时
proxy_connect_timeout 2;
#读取服务器资源超时
proxy_read_timeout 2;
#向服务器发送数据超时
proxy_send_timeout 2;
}
}
}">设定负载均衡策略 名称不要加”_”线 1.默认规则 轮询
upstream jt-windows {
#ip_hash;
server 127.0.0.1:8091 max_fails=1 fail_timeout=60s;
server 127.0.0.1:8092 max_fails=1 fail_timeout=60s;
server 127.0.0.1:8093 max_fails=1 fail_timeout=60s;
}
#后台管理服务器 用户访问manage.jt.com时访问localhost:8091
server {
listen 80;
server_name manage.jt.com;
location / {
#代理路径
proxy_pass http://jt-windows;
#链接服务器超时
proxy_connect_timeout 2;
#读取服务器资源超时
proxy_read_timeout 2;
#向服务器发送数据超时
proxy_send_timeout 2;
}
}
} - 4、Linux
- 4、Redis
-
">5.0版本执行 使用C语言内部管理集群
redis-cli —cluster create —cluster-replicas 1 192.168.35.130:7000 192.168.35.130:7001 192.168.35.130:7002 192.168.35.130:7003 192.168.35.130:7004 192.168.35.130:7005
- 5.12 常见面试题
- 6、微服务
- 7、Dubbo框架
- 8、Quartz定时任务
1、SpringBoot
1.1 概念
Spring Boot是构建所有基于Spring的应用程序的起点。Spring Boot旨在尽可能快地启动和运行,只需最少的Spring前端配置。自己内部添加了单独tomcat服务器.要求项目尽可能独立运行.
2、分布式
2.1分布式概念
将业务模块按照特定的规则进行拆分.分别部署到不同的服务器实现了架构的解耦.
传统项目:
存在问题:
1:模块之间耦合度太高,其中一个功能升级,其他的模块都得一起升级部署。
2:开发困难,各个团队开发最后都要整合在一起.
3:系统扩展性差
4:不能灵活进行分布式部署
解决方案:
把模块才分成独立的工程,单节点运行,如果某一个节点压力大了可以单独对这个节点进行增加配置,其他节点不受影响。缺点就是系统之间交互
需要额外的工作量来进行接口的开发。把系统拆分成多个工程,需要完成系统的工程需要多个工程协作完成,这种形式就叫做分布式。
分布式:
把系统拆分成多个子系统.优点:
1:把模块拆分,使用接口通信,降低模块之间的耦合度.
2:把项目拆分成若干个子项目,不同的团队负责不同的子项目.
3:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
4:可以灵活的进行分布式部署.
5:提高代码的复用性,比如service层,如果不采用分布式rest服务方式架构就会在手机wap商城,微信商城,pc,android,ios每个端都要写一个service层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式rest服务方式,公用一个service层。
缺点:系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。
2.2分布式项目拆分
垂直拆分:
说明:按照项目的功能(业务)模块进行拆分.将不同的业务部署到不同的服务器中.
水平拆分:
场景:一个service可能3000行代码由一个人完成controller-Service-mapper任务繁重.这时需要多个人开发!!
概念:按照调用的层级进行拆分.
2.3分布式项目总结
2.3 分布式事务
1、分布式事务和分布式锁?
比如从支付宝转100元到余额宝,我们又两个方法1、支付宝减掉100,2、余额宝加上100。传统的在一个模块,一个服务,或者一个方法里面,我们就很好解决了,只需要注解一个事务就行了。
@Transactional(rollbackFor=Exception.class) 这样我们就可以保证两个方法数据的一致性了。但是显然,现在我们的项目中,为了满足性能要求,不可能还这样传统单机实现。我们做成了两个服务,在两个不同的模块 1、支付宝,2、余额宝 这样就存在了我们提到的问题,分布式事务,这个时候如何解决呢?
通常来说呢 实现方式有如下几种:
1、两阶段提交协议(Two-phase Commit,2PC):架构图如下
简单来说,协调器先给A/B各发一条,准备的命令,等到都返回准备好了的命令的时候,再发起事务提交。这样来保证事务一致性,但是存在很多问题,就是通信上中断的情况,会导致事务一致无法提交,而可能使系统崩溃。这就可以使用第二种方案。
第二种方案:TCC补偿性,分为三个阶段TRYING-CONFIRMING-CANCELING。每个阶段做不同的处理。
TRYING:阶段主要是对业务系统进行检测及资源预留
CONFIRMING:阶段是做业务提交,通过TRYING阶段执行成功后,再执行该阶段。
(默认如果TRYING:阶段执行成功,CONFIRMING就一定能成功。)
CANCELING:阶段是回对业务做回滚,在TRYING阶段中,如果存在分支事务TRYING失败,则需要调用CANCELING将已预留的资源进行释放。
什么是分布式锁?
场景1:常规的我们多线程访问同一代码块的时候,为了保证同一时间只能
由一个线程访问,保证数据安全一致性,通常我们使用synchronized关键字来对方法加锁,以达到保证数据安全性。
场景2:现在越来越多的项目,为了追求性能与高并发,采用了soa架构,微服务架构,于是就会出现多个模块单独的服务。这个时候呢就会有一个问题,如何保证多个节点的现场同步执行呢?
这种情况呢,就会用到了分布式锁。
分布式锁的解决方案与实现有哪些呢?
1、数据库解决方案思路:
a.数据库建一张表,字段方法名并且作为唯一性,当一个方法执行时插入,则相当于获得锁,其他线程将无法访问,方法执行完则释放锁。但是上面这种存在问题:
1、数据库单点,出现故障则将导致系统不可用。2、没有失效时间,一旦操作方法异常,导致一直没有解锁,也将导致其他不可用。
b.使用select * from user u where username = ‘’ for update 来对记录加上排他锁。操作完成后使用commit命令释放锁。
2、基于缓存实现: 通常有Memcached、Redis实现等,以下以Redis实现分布式锁为例
思路:主要用到的redis函数是setnx(),这个应该是实现分布式锁最主要的函数。首先是将某一任务标识名(这里用Lock:order作为标识名的例子)作为键存到redis里,并为其设个过期时间,如果是还有Lock:order请求过来,先是通过setnx()看看是否能将Lock:order插入到redis里,可以的话就返回true,不可以就返回false
3.Zookeeper分布式锁
大致思路:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。
判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。
当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上,所以性能上不如基于缓存实现。
3、Ngnix
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
3.1 Nginx配置文件介绍
server代表一个服务项
server {
listen 80; #监听端口
#server_name 表示拦截域名
server_name localhost;
#拦截请求之后处理方式
location / {
#root 是关键字 代表反向代理的文件夹名称
root html;
#index 默认跳转页面
index index.html index.htm;
}
}
如配置图片代理,并修改hosts文件
#配置图片服务器
server {
listen 80;
server_name image.jt.com;
location / {
root D:/1-jt/image;
}
}
实现域名代理
#后台管理服务器 用户访问manage.jt.com时访问localhost:8091
server {
listen 80;
server_name manage.jt.com;
location / {
#代理路径
proxy_pass http://localhost:8091;
}
}
3.2 实现负载均衡(Tomcat高可用)
设定负载均衡策略 名称不要加”_”线 1.默认规则 轮询
upstream jt-windows {
#ip_hash;
server 127.0.0.1:8091 max_fails=1 fail_timeout=60s;
server 127.0.0.1:8092 max_fails=1 fail_timeout=60s;
server 127.0.0.1:8093 max_fails=1 fail_timeout=60s;
}
#后台管理服务器 用户访问manage.jt.com时访问localhost:8091
server {
listen 80;
server_name manage.jt.com;
location / {
#代理路径
proxy_pass http://jt-windows;
#链接服务器超时
proxy_connect_timeout 2;
#读取服务器资源超时
proxy_read_timeout 2;
#向服务器发送数据超时
proxy_send_timeout 2;
}
}
}
3.3 常见面试题
1、请解释一下什么是Nginx?
Nginx是一个web服务器和反向代理服务器,用于HTTP、HTTPS、SMTP、POP3和IMAP协议。
2、请列举Nginx的一些特性。
Nginx服务器的特性包括:
反向代理/负载均衡器
嵌入式Perl解释器
动态二进制升级
可用于重新编写URL,具有非常好的PCRE支持
3、请列举Nginx和Apache 之间的不同点。
4、请解释Nginx如何处理HTTP请求。
Nginx使用反应器模式。主事件循环等待操作系统发出准备事件的信号,这样数据就可以从套接字读取,在该实例中读取到缓冲区并进行处理。单个线程可以提供数万个并发连接。
5、在Nginx中,如何使用未定义的服务器名称来阻止处理请求?
只需将请求删除的服务器就可以定义为:
Server {
listen 80;
server_name “ “ ;
return 444;
}
这里,服务器名被保留为一个空字符串,它将在没有“主机”头字段的情况下匹配请求,而一个特殊的Nginx的非标准代码444被返回,从而终止连接。
6、 使用“反向代理服务器”的优点是什么?
反向代理服务器可以隐藏源服务器的存在和特征。它充当互联网云和web服务器之间的中间层。这对于安全方面来说是很好的,特别是当您使用web托管服务时。
7、请列举Nginx服务器的最佳用途。
Nginx服务器的最佳用法是在网络上部署动态HTTP内容,使用SCGI、WSGI应用程序服务器、用于脚本的FastCGI处理程序。它还可以作为负载均衡器。
8、请解释Nginx服务器上的Master和Worker进程分别是什么?
Master进程:读取及评估配置和维持
Worker进程:处理请求
9、请解释你如何通过不同于80的端口开启Nginx?
为了通过一个不同的端口开启Nginx,你必须进入/etc/Nginx/sites-enabled/,如果这是默认文件,那么你必须打开名为“default”的文件。编辑文件,并放置在你想要的端口:
Like server { listen 81; }
10、请解释是否有可能将Nginx的错误替换为502错误、503?
502 = 错误网关
503 = 服务器超载
有可能,但是您可以确保fastcgi_intercept_errors被设置为ON,并使用错误页面指令。
Location / {
fastcgi_pass 127.0.01:9001;
fastcgi_intercept_errors on;
error_page 502 =503/error_page.html;
#…
11、在Nginx中,解释如何在URL中保留双斜线?
要在URL中保留双斜线,就必须使用merge_slashes_off;
语法:merge_slashes [on/off]
默认值: merge_slashes on
环境: http,server
12、请解释ngx_http_upstream_module的作用是什么?
ngx_http_upstream_module用于定义可通过fastcgi传递、proxy传递、uwsgi传递、memcached传递和scgi传递指令来引用的服务器组。
13、请解释什么是C10K问题?
C10K问题是指无法同时处理大量客户端(10,000)的网络套接字。
14、请陈述stub_status和sub_filter指令的作用是什么?
Stub_status指令:该指令用于了解Nginx当前状态的当前状态,如当前的活动连接,接受和处理当前读/写/等待连接的总数
Sub_filter指令:它用于搜索和替换响应中的内容,并快速修复陈旧的数据
15、解释Nginx是否支持将请求压缩到上游?
您可以使用Nginx模块gunzip将请求压缩到上游。gunzip模块是一个过滤器,它可以对不支持“gzip”编码方法的客户机或服务器使用“内容编码:gzip”来解压缩响应。
16、解释如何在Nginx中获得当前的时间?
要获得Nginx的当前时间,必须使用SSI模块、$date_gmt和$date_local的变量。
Proxy_set_header THE-TIME $date_gmt;
17、用Nginx服务器解释-s的目的是什么?
用于运行Nginx -s参数的可执行文件。
18、解释如何在Nginx服务器上添加模块?
在编译过程中,必须选择Nginx模块,因为Nginx不支持模块的运行时间选择。
19、Nginx负载均衡策略?
轮询、权重、依据ip分配方式、最少连接方式、响应时间方式、依据URL分配方式
4、Linux
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
Linux操作系统诞生于1991 年10 月5 日(这是第一次正式向外公布时间)。Linux存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。
严格来讲,Linux这个词本身只表示Linux内核,但实际上人们已经习惯了用Linux来形容整个基于Linux内核,并且使用GNU工程各种工具和数据库的操作系统。
4.1 Linux命令
4.1.1 cd命令集
ifconfig 检查IP地址 ip addr
pwd 查找当前文件位置
cd命令是linux中最基本的命令语句,必须熟练掌握
cd / 返回根目录
cd ~ 用户主目录
cd . 当前目录
cd ..返回到上一级目录
cd /usr/ 进入到usr目录
cd – 返回上一个目录
cd 直接回家
4.1.2 ls目录和文件
ls 展现文件目录
ll 展现文件详情
ls –l 详细格式,文件权限,时间
ll 和ls –l作用相同
ls *.txt 查看所有的txt类型文档
4.1.3目录操作
mkdir 创建目录
mkdir a 创建 a目录
mkdir -p a/b 创建 a目录,并在a目录里创建b目录
mkdir -m 777 c 创建一个权限为777的C目录
rmdir 删除目录(如果目录里有文件,则不能用此命令)
4.1.4 Vi/vim创建/查看/编辑文件
命令行:Esc切换到命令行模式。
编辑模式:
按i,在光标前开始编辑
按a,在光标后开始编辑
按o,在当前行的下一行开始编辑
按u 撤销之前的操作
底行模式:按 shift+:冒号。
:q! 不保存退出
:wq 保存退出
:/world 从当前光标处,向上查找world关键字
:?world 从当前光标处,向后查找world关键字
4.1.5 删除文件
rm 删除文件
rm n.txt 提示y删除n放弃
rm –f n.txt 不提示
rm –rf dirname 不提示递归删除目录下所以内容
rm –rf 删除所有文件
rm –rf / 删除所有子目录所有和文件
4.1.6 复制和移动文件
cp复制文件
cp nginx.conf n.txt
cp –R tomcat1 tomcat2 #复制整个目录
mv 修改文件名,移动文件
mv n.txt m.txt
4.1.7 浏览文件
cat 输出文件所有的内容
more 输出文档所有的内容,分页输出,空格浏览下一屏,q退出
less 用法和more相同,只是通过PgUp、PgOn键来控制
tail 用于显示文件后几号,使用频繁
tail -10 nginx.conf 查看nginx.conf的最后10行
tail –f nginx.conf 动态查看日志,方便查看日志新增的信息
ctrl+c 结束查看
4.1.8 打包命令
tar命令位于/bin目录下,它能够将用户所指定的文件或目录打包成一个文件,但不做压缩。一般Linux上常用的压缩方式是选用tar将许多文件打包成一个文件,再以gzip压缩命令压缩成name.tar.gz的文件。
-c 创建一个新的tar文件
-v 显示运行过程的信息
-f 指定文件名
-z 调用gzip压缩命令进行压缩
-t 查看压缩文件的内容
-x 解开tar文件
tar –cvf n.tar ./ 压缩当前目录下的所有文件和目录,文件名为n.tar
tar –xvf n.tar 解压压缩包中的文件到当前目录(如果长时间未解压成功 Ctrl+C推出)
tar –cvzf m.tar ./ 解压m.tar文件到当前目录
4.1.9 grep命令
grep root /etc/passwd 在文件中查找关键字root
grep root /etc/passwd –-color 高亮显示
grep root /etc/passwd –A5 –B5 高亮显示,A后5行,B前5行
grep -n root /etc/passwd 查找并显示行数
grep -v root /etc/passwd 取反,查出不含root的数据
4、Redis
5.1 简介
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hash), 列表(list), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
常见API:
Jedis jedis = new Jedis(“localhost”);
ShardedJedisPool连接池分片
5.2 Redis命令
5.2.1 String类型
命令 | 说明 | 案例 |
---|---|---|
set | 添加key-value | set username admin |
get | 根据key获取数据 | get username |
strlen | 获取key的长度 | strlen key |
exists | 判断key是否存在 | exists name 返回1存在 0不存在 |
del | 删除redis中的key | del key |
Keys | 用于查询符合条件的key | keys 查询redis中全部的key keys n?me 使用占位符获取数据 keys nam 获取nam开头的数据 |
mset | 赋值多个key-value | mset key1 value1 key2 value2 key3 value3 |
mget | 获取多个key的值 | mget key1 key2 |
append | 对某个key的值进行追加 | append key value |
type | 检查某个key的类型 | type key |
select | 切换redis数据库 | select 0-15 redis中共有16个数据库 |
flushdb | 清空单个数据库 | flushdb |
flushall | 清空全部数据库 | flushall |
incr | 自动加1 | incr key |
decr | 自动减1 | decr key |
incrby | 指定数值添加 | incrby 10 |
decrby | 指定数值减 | decrby 10 |
expire | 指定key的生效时间 单位秒 | expire key 20 key20秒后失效 |
pexpire | 指定key的失效时间 单位毫秒 | pexpire key 2000 key 2000毫秒后失效 |
ttl | 检查key的剩余存活时间 | ttl key |
persist | 撤销key的失效时间 | persist key |
5.2.2 Hash类型
说明:可以用散列类型保存对象和属性值
例子:User对象{id:2,name:小明,age:19}
命令 | 说明 | 案例 |
---|---|---|
hset | 为对象添加数据 | hset key field value |
hget | 获取对象的属性值 | hget key field |
hexists | 判断对象的属性是否存在 | HEXISTS key field 1表示存在 0表示不存在 |
hdel | 删除hash中的属性 | hdel user field [field …] |
hgetall | 获取hash全部元素和值 | HGETALL key |
hkyes | 获取hash中的所有字段 | HKEYS key |
hlen | 获取hash中所有属性的数量 | hlen key |
hmget | 获取hash里面指定字段的值 | hmget key field [field …] |
hmset | 为hash的多个字段设定值 | hmset key field value [field value …] |
hsetnx | 设置hash的一个字段,只有当这个字段不存在时有效 | HSETNX key field value |
hstrlen | 获取hash中指定key的长度 | HSTRLEN key field |
hvals | 获取hash的所有值 | HVALS user |
5.2.3 List类型
说明:Redis中的List集合是双端循环列表,分别可以从左右两个方向插入数据.
List集合可以当做队列使用,也可以当做栈使用
队列:存入数据的方向和获取数据的方向相反
栈:存入数据的方向和获取数据的方向相同
命令 | 说明 | 案例 |
---|---|---|
lpush | 从队列的左边入队一个或多个元素 | LPUSH key value [value …] |
rpush | 从队列的右边入队一个或多个元素 | RPUSH key value [value …] |
lpop | 从队列的左端出队一个元素 | LPOP key |
rpop | 从队列的右端出队一个元素 | RPOP key |
lpushx | 当队列存在时从队列的左侧入队一个元素 | LPUSHX key value |
rpushx | 当队列存在时从队列的右侧入队一个元素 | RPUSHx key value |
lrange | 从列表中获取指定返回的元素 | LRANGE key start stop Lrange key 0 -1 获取全部队列的数据 |
lrem | 从存于 key 的列表里移除前 count 次出现的值为 value 的元素。 这个 count 参数通过下面几种方式影响这个操作: · count > 0: 从头往尾移除值为 value 的元素。 · count < 0: 从尾往头移除值为 value 的元素。 · count = 0: 移除所有值为 value 的元素。 |
LREM list -2 “hello” 会从存于 list 的列表里移除最后两个出现的 “hello”。 需要注意的是,如果list里没有存在key就会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 0。 |
Lset | 设置 index 位置的list元素的值为 value | LSET key index value |
5.2.4 Redis事务命令
说明:redis中操作可以添加事务的支持.一项任务可以由多个redis命令完成,如果有一个命令失败导致入库失败时.需要实现事务回滚.
命令 | 说明 | 案例 |
---|---|---|
multi | 标记一个事务开始 | 127.0.0.1:6379> MULTI OK |
exec | 执行所有multi之后发的命令 | 127.0.0.1:6379> EXEC OK |
discard | 丢弃所有multi之后发的命令 |
5.3 SpringBoot整合Redis
1、编辑redis.properties文件:
jedis.host=192.168.175.129
jedis.port=6379
2、编辑配置类:
//表示redis配置类
@Configuration //定义配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${jedis.host}")
private String host;
@Value("${jedis.port}")
private Integer port;
@Bean
public Jedis jedis() {
return new Jedis(host, port);
}
}
5.4 常见注解
5.4.1 @RequestParam
@RequestParam(value=”aa” required=false)
1、可以对传入参数指定参数名:@RequestParam(value=”aa”)
2、可以通过required=false或者true来要求@RequestParam配置的前端参数是否一定要传 :@RequestParam(value=”aa”, required=true)
3、如果@requestParam注解的参数是int类型,并且required=false,此时如果不传参数的话,会报错。原因是,required=false时,不传参数的话,会给参数赋值null,这样就会把null赋值给了int,因此会报错。
5.5 Redis分片机制
核心特点:实现了redis内存的扩容.
说明:使用多个redis节点,共同为用户提供服务.内存空间翻倍.用户使用时当做一个整体.并且内存保存的数据不一.
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
JedisShardInfo info1 = new JedisShardInfo("192.168.175.129",6379);
JedisShardInfo info2 = new JedisShardInfo("192.168.175.129",6380);
JedisShardInfo info3 = new JedisShardInfo("192.168.175.129",6381);
shards.add(info1);
shards.add(info2);
shards.add(info3);
5.5.1 哈希一致性
概念:同一个字符串hash值是一致的
分片数据存储原理: 根据hash一致性算法实现数据存储.
Hash一致性运算发生在服务器端.
一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法,常用于负载均衡。Memcached client也选择这种算法,解决将key-value均匀分配到众多Memcached server上的问题。它可以取代传统的取模操作,解决了取模操作无法应对增删Memcached Server的问题(增删server会导致同一个key,在get操作时分配不到数据真正存储的server,命中率会急剧下降)。
简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环
哈希一致性的特性:
因为所有节点都是通过ip地址加算法计算获取的,则可能会出现节点分配不均的问题.导致数据丢失.
均衡性
说明:均衡性要求节点中的数据尽可能的平均.
措施:引入虚拟节点概念
单调性
说明:当节点新增时,能够实现数据的自动的迁移.
补充说明:如果节点一旦丢失,则导致内存丢失则整个分片无法使用.
分散性:
概念:由于分布式原因,导致系统不能获取全部的内存空间.导致一个key有多个位置.
负载:
概念:由于分布式原因,系统不能获取全部的内存地址.导致同一个位置保存多个数据
5.6 Redis持久化策略
Redis中的数据都在内存中,如果断电宕机则内存数据丢失.其中数据应该持久化保存.不允许丢失.
持久化策略:
1. RDB模式(默认机制)
2. AOF模式
5.6.1 Redis持久化工作原理
说明:按照配置的时间,定期将内存数据保存到redis中的持久化文件中.
当redis服务器宕机之后重启时,首先读取指定的持久化文件,恢复内存数据,方便用户使用.
5.6.2 RDB模式
概念:RDB模式是Redis中默认的持久化策略.保存的是redis的内存快照.占用的资源少.持久化效率最高的.
RDB特点:
1.RDB模式能够定期持久化,但是有丢失数据的风险.
2.Redis中默认的持久化策略
3.RDB模式做内存的快照. 效率高
4.占用磁盘空间较小.
5.6.3 AOF模式(Append Only File)
特点:
1. AOF模式可以实现数据的实时持久化.
2. 记录的是用户的操作过程.
3. 持久化文件会比较大.
4. 持久化效率低.
5. AOF模式默认是关闭的
6. AOF模式持久化是异步的.
5.6.4 Redis缓存策略说明
- 如果有并发查询时.如果缓存服务器宕机/缓存失效.则查询数据库.可能导致数据库宕机. 俗称:缓存雪崩.
2. 如果用户,高并发查询一个不存在的数据时.后台数据库有宕机的风险.
俗称:缓存穿透 (数据库不存在的数据,“透”:穿透redis层、穿透数据库层)
限流 直至封杀IP地址. IP模拟器
3. 如果高并发条件下.当某一个热点的key,超时或者失效时.数据库有宕机的风险.
俗称:缓存击穿 (数据库存在的数据)
5.6.5 Redis缓存策略
- 缓存穿透
- 定义:请求的是缓存跟数据库都没有的数据!
- 解决方案:缓存NULL值,在spring-cache中有配置 spring.cache.redis.cache-null-values=true 、方法上@Cacheable(“XXX”)
- 缓存击穿
- 请求的是缓存没有,而数据库中有的数据!
- 解决方案:@Cacheable(cacheNames=”XXX”,sync=”true”) 使用该属性后,可以指示底层将缓存锁住,使只有一个线程可以进入计算,而其他的线程堵塞,直到返回结果更新到缓存中。
- 缓存雪崩
- 某个时间点所有的缓存全部过期!
- 解决方案:添加过期时间随机值
5.7 Redis内存机制
Redis中的数据都保存内存中.内存中的数据如果一味的新增,不删除则内存数据很快存满.导致新的数据保存错误.
需求:用户每次都能存储数据,但是内存大小是可控的.要求动态维护内存大小.
5.7.1 Redis中内存策略
LRU算法:
内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。
LRU(Least recently used,最近最少使用(按时间))算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
LFU算法
LFU(least frequently used (LFU) page-replacement algorithm)。即最不经常使用(按次数)页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
LFU:根据数据使用的次数多少删除数据.
内存优化策略
1. volatile-lru
设定超时时间的数据采用LRU算法删除数据.
2. allkeys-lru
所有的数据采用LRU算法删除数据
3. volatile-lfu
设定了超时时间的数据采用LFU删除数据
4. allkeys-lfu
所有的数据采用LFU算法删除数据
5. volatile-random
设定了超时时间的随机删除
6. allkeys-random
所有key随机删除
7. volatile-ttl
设定了超时时间的数据排序.将马上要超时的数据提前删除.
8. Noeviction
不删除数据.如果内存数据存满则报错返回. 该策略是默认策略
5.8 Redis主从同步
5.8.1高可用介绍(HA)
“高可用性”(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。
概括:利用技术手段实现了当服务器宕机,自动的实现故障的迁移.
Redis的最终形态必须实现高可用,实现高可用的前提必须满足主从同步.
当发生故障,由于从机与主机的数据是相同的,所以可以非常灵活实现数据的故障迁移.
5.9 Redis哨兵实现高可用
5.9.1 Redis中哨兵的作用
分片作用:redis分片实现了redis内存扩容.
Redis哨兵:主要实现了redis节点的高可用.
5.9.2 Redis哨兵实现步骤
- redis哨兵会监听redis主节点.
目的1:检查主节点是否存活
目的2:获取连接主节点的从机. IP:端口
2. 当利用ping-pong(心跳检测)检测机制.检查主节点是否存活,当哨兵连续3次检测都没有数据返回.则表明主节点宕机.
3. 哨兵根据从主节点获取的从节点信息,进行推选.从中挑选一台新的从节点当做现在的主节点.将新的主从关系写入其他节点的redis.conf文件中.
4. 当服务器重启后,能够了解当前主从关系,实现了redis高可用.
5.10 分片与哨兵的缺点
- Redis分片
用户通过API利用hash一致性算法,实现了数据存储.利用分片机制实现了内存的扩容!!!
缺点:如果一个节点宕机.,则违反单调性要求,分片失效.
2. Redis哨兵
哨兵基于心跳检测机制.实现redis节点高可用.但是前提必须配置主从.
哨兵缺点:
1. 操作的redis依然是单台,内存无法扩容.
2. Redis哨兵也有可能宕机.5.11 Redis集群(Redis最终形态)
说明:搭建redis集群可以实现redis分片和哨兵的全部功能!!!.Redis集群中所有的主节点参与选举.redis集群中全部的节点都能互相通信.所有的节点都有投票权(发现某个节点宕机投票数+1)
最小的集群单位3个主节点,从机不做要求,搭建策略一主一从
主机3台
端口:7000/7001/7002
从机3台
端口:7003/7004/7005
5.11.1 准备集群文件夹
1.准备集群文件夹
Mkdir cluster
2.在cluster文件夹中分别创建7000-7005文件夹
5.11.2 复制配置文件
说明:
将redis根目录中的redis.conf文件复制到cluster/7000/ 并以原名保存
cp redis.conf cluster/7000/5.11.3 编辑配置文件
- 注释本地绑定IP地址
2. 关闭保护模式
3. 修改端口号
4. 启动后台启动
5. 修改pid文件
6. 修改持久化文件路径
7. 设定内存优化策略
8. 关闭AOF模式
9. 开启集群配置
10. 开启集群配置文件
保存集群中的状态信息.谁是主机,谁是从机.
11. 修改集群超时时间
5.11.4 复制修改后的配置文件
说明:将7000文件夹下的redis.conf文件分别复制到7001-7005中
[root@localhost cluster]# cp 7000/redis.conf 7001/
[root@localhost cluster]# cp 7000/redis.conf 7002/
[root@localhost cluster]# cp 7000/redis.conf 7003/
[root@localhost cluster]# cp 7000/redis.conf 7004/
[root@localhost cluster]# cp 7000/redis.conf 7005/5.11.5 批量修改
说明:分别将7001-7005文件中的7000改为对应的端口号的名称,
修改时注意方向键的使用
5.11.6 通过脚本编辑启动/关闭指令
- 创建启动脚本 vim start.sh
2. 编辑关闭的脚本 vim shutdown.sh
3. 启动redis节点
sh start.sh
4. 检查redis节点启动是否正常
5.11.7 创建redis集群
5.0版本执行 使用C语言内部管理集群
redis-cli —cluster create —cluster-replicas 1 192.168.35.130:7000 192.168.35.130:7001 192.168.35.130:7002 192.168.35.130:7003 192.168.35.130:7004 192.168.35.130:7005
5.11.8 Redis集群高可用测试
- 关闭redis主机.检查是否自动实现故障迁移.
2. 再次启动关闭的主机.检查是否能够实现自动的挂载.
一般情况下 能够实现主从挂载
个别情况: 宕机后的节点重启,可能挂载到其他主节点中(7001-7002) 正确的
5.12 常见面试题
1、什么是 Redis?简述它的优缺点?
Redis 的全称是:Remote Dictionary.Server,本质上是一个 Key-Value 类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存。
因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的Key-Value DB。
Redis 的出色之处不仅仅是性能,Redis 最大的魅力是支持保存多种数据结构,此外单个 value 的最大限制是 1GB,不像 memcached 只能保存 1MB 的数据,因此 Redis 可以用来实现很多有用的功能。
比方说用他的 List 来做 FIFO 双向链表,实现一个轻量级的高性 能消息队列服务,用他的 Set 可以做高性能的 tag 系统等等。
另外 Redis 也可以对存入的 Key-Value 设置 expire 时间,因此也可以被当作一 个功能加强版的memcached 来用。 Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
2、Redis 与 memcached 相比有哪些优势?
memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型
redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多
redis 可以持久化其数据 redis 可以持久化其数据
3、Redis 支持哪几种数据类型?
String、List、Set、Sorted Set、hashes
4、Redis 主要消耗什么物理资源?
内存。
5、Redis 有哪几种数据淘汰策略?
- noeviction:返回错误当内存限制达到,并且客户端尝试执行会让更多内存被使用的命令。
- allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
- volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
6、Redis 官方为什么不提供 Windows 版本?
因为目前 Linux 版本已经相当稳定,而且用户量很大,无需开发 windows 版本,反而会带来兼容性等问题。
7、一个字符串类型的值能存储最大容量是多少?
512M
8、为什么 Redis 需要把所有数据放到内存中?
Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征,如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能。
在内存越来越便宜的今天,redis 将会越来越受欢迎, 如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
9、Redis 集群方案应该怎么做?都有哪些方案?
- codis
- 目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在节点数量改变情况下,旧节点数据可恢复到新 hash 节点。
- redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持节点设置从节点。具体看官方文档介绍。
- 在业务代码层实现,起几个毫无关联的 redis 实例,在代码层,对 key 进行 hash 计算,然后去对应的redis 实例操作数据。这种方式对 hash 层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。
Java 架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm 性能调优、Spring 源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx 等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用”没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
10、Redis 集群方案什么情况下会导致整个集群不可用?
有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了,那么整个集群就会以为缺少5501-11000 这个范围的槽而不可用。
11、MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中的数据都是热点数据?
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
12、Redis 有哪些适合的场景?
(1)会话缓存(Session Cache)
最常用的一种使用 Redis 的情景是会话缓存(sessioncache),用 Redis 缓存会话比其他存储(如Memcached)的优势在于:Redis 提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用 Redis 来缓存会话的文档。甚至广为人知的商业平台 Magento 也提供 Redis 的插件。
(2)全页缓存(FPC)
除基本的会话 token 之外,Redis 还提供很简便的 FPC 平台。回到一致性问题,即使重启了 Redis 实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似 PHP 本地FPC。
再次以 Magento 为例,Magento 提供一个插件来使用 Redis 作为全页缓存后端。
此外,对 WordPress 的用户来说,Pantheon 有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
(3)队列
Reids 在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得 Redis 能作为一个很好的消息队列平台来使用。Redis 作为队列使用的操作,就类似于本地程序语言(如 Python)对 list 的 push/pop操作。
如果你快速的在 Google 中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用 Redis 创建非常好的后端工具,以满足各种队列需求。例如,Celery 有一个后台就是使用Redis 作为 broker,你可以从这里去查看。
(4)排行榜/计数器
Redis 在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单,Redis 只是正好提供了这两种数据结构。
所以,我们要从排序集合中获取到排名最靠前的 10 个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORESAgora Games 就是一个很好的例子,用 Ruby 实现的,它的排行榜就是使用 Redis 来存储数据的,你可以在这里看到。
(5)发布/订阅
最后(但肯定不是最不重要的)是 Redis 的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用 Redis 的发布/订阅功能来建立聊天系统!
13、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?
Redisson、Jedis、lettuce 等等,官方推荐使用 Redisson。
15、Jedis 与 Redisson 对比有什么优缺点?
Jedis 是 Redis 的 Java 实现的客户端,其 API 提供了比较全面的 Redis 命令的支持;
Redisson 实现了分布式和可扩展的 Java 数据结构,和 Jedis 相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等 Redis 特性。Redisson 的宗旨是促进使用者对 Redis 的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
16、说说 Redis 哈希槽的概念?
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
17、Redis 集群的主从复制模型是怎样的?
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有 N-1 个复制品.
18、Redis 集群会有写操作丢失吗?为什么?
Redis 并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
19、Redis 集群之间是如何复制的?
异步复制
20、Redis 集群最大节点个数是多少?
16384 个
21、Redis 集群如何选择数据库?
Redis 集群目前无法做数据库选择,默认在 0 数据库。
22、Redis 中的管道有什么用?
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应,这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多 POP3 协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。
23、怎么理解 Redis 事务?
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行,事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
24、Redis 事务相关的命令有哪几个?
MULTI、EXEC、DISCARD、WATCH
25、Redis key 的过期时间和永久有效分别怎么设置?
EXPIRE 和 PERSIST 命令
26、Redis 如何做内存优化?
尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。
比如你的 web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的 key,而是应该把这个用户的所有信息存储到一张散列表里面。
27、Redis 回收进程如何工作的?
一个客户端运行了新的命令,添加了新的数据。Redi 检查内存使用情况,如果大于 maxmemory 的限制, 则根据设定好的策略进行回收。一个新的命令被执行,等等。
所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。 如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。
34.使用过 Redis 分布式锁么,它是怎么实现的?
先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了,那会怎么样?set 指令有非常复杂的参数,这个应该是可以同时把 setnx 和 expire 合成一条指令来用的!
35.使用过 Redis 做异步队列么,你是怎么用的?有什么缺点?
一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有消息的时候,要适当 sleep一会再重试。
缺点:在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 rabbitmq 等。
- 能不能生产一次消费多次呢?
- 使用 pub/sub 主题订阅者模式,可以实现 1:N 的消息队列。
36.何如避免缓存穿透、缓存雪崩?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
2:做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期
3:不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀
6、微服务
6.1概念
在分布式的基础之上.服务可以独立的运行.当服务发生故障时,可以实现故障的自动化迁移.用户无需关注.
6.2 SOA思想
面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
6.3 RPC协议
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
6.4 OSI模型(网络7层协议规范)
6.5 RPC与HTTP区别
区别:
1.RPC是传输层协议(4层).而HTTP协议是应用层协议(7层).
2.RPC协议可以直接调用中立接口,HTTP协议不可以.
3.RPC通信协议是长链接,HTTP协议一般采用短连接需要3次握手(可以配置长链接添加请求头Keep-Alive: timeout=20).
(长连接,指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。)
4.RPC协议传递数据是加密压缩传输.HTTP协议需要传递大量的请求头信息.
5.RPC协议一般都有注册中心.有丰富的监控机制.
6.6 RPC总结
RPC叫远程过程调用.它是OSI模型中第四层协议.封装了四层以下的通讯方式.使用户不需要了解tcp/udp等网络传输协议,也能实现数据的传输.同时RPC一般使用时需要配置注册中心.
6.7注册中心
1. 当服务启动时,将服务信息服务名称/IP/端口写入注册中心.
2. 注册中心接收服务端信息时保存服务信息,并且维护服务列表数据
3. 当服务消费者启动时会通过IP:端口(注册中心)远程链接注册中心.
获取服务列表信息.缓存到本地
4. 当消费者调用服务时,查找缓存到本地的服务列表信息.之后通过负载均衡机制挑选其中一个服务进行访问.
5. 当后台服务器宕机时,由于注册中心有心跳检测机制.所以可以发现某台服务器宕机.之后更新自己的服务列表信息.之后广播给全部消费者.
6. 当消费者获取服务列表的通知时,最终更新本地的服务列表数据.
6.2 Zookeeper注册中心
6.2.1 Zookeeper介绍
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.3\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
总结:zookeeper是服务的协调调度服务器!!!
6.2.2 zookeeper集群说明
Zookeeper集群中leader负责监控集群状态,follower主要负责客户端链接获取服务列表信息.同时参与投票.
7、Dubbo框架
7.1介绍
Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
7.2 Dubbo工作原理
1. consumer 服务消费者
2. provider 服务提供者
3. registry 注册中心
基于SOA思想
7.3负载均衡说明
说明:dubbo默认的负载均衡策略是随机发送!!!!!
策略:
1. LoadBalance:Random 随机发起请求 该配置是默认的
2. LoadBalance:RoundRobin 权重相同时轮询策略
3. LoadBalance:LeastActive 根据响应时间的长短实现负载均衡.如果服务器响应时间越短,则用户会将大量的请求发送给该服务器.
4. LoadBalance:ConsistentHash
根据hash算法实现负载均衡.实现服务器绑定.
配置方式:
可以在服务端/客户端通过注解的形式配置.引用时将负载均衡类名前缀小写即可.
@Reference(timeout = 3000,check=false,loadbalance =”random”)
@Reference(timeout = 3000,check=false,loadbalance =”roundrobin”)
@Reference(timeout = 3000,check=false,loadbalance =”leastactive”)
@Reference(timeout = 3000,check=false,loadbalance =”consistenthash”)
7.4 Dubbo面试题
1、当注册中心宕机后,dubbo能否继续提供服务.
依然可以正确访问.因为消费者启动时已经将服务列表数据缓存到本地.
2.Dubbo是什么?
Dubbo 是一个分布式、高性能、透明化的 RPC 服务框架,提供服务自动注册、自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成。
RPC 指的是远程调用协议,也就是说两个服务器交互数据。
3、为什么要用Dubbo?
因为是阿里开源项目,国内很多互联网公司都在用,已经经过很多线上考验。内部使用了 Netty、Zookeeper,保证了高性能高可用性。
使用 Dubbo 可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可用于提高业务复用灵活扩展,使前端应用能更快速的响应多变的市场需求。
4、Dubbo 和 Spring Cloud 有什么区别?
两个没关联,如果硬要说区别,有以下几点。
通信方式不同
Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式。
5、Dubbo的核心功能?
主要就是如下3个核心功能:
Remoting:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。
Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
6、Dubbo有些哪些注册中心?
Multicast注册中心: Multicast注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现。基于网络中组播传输实现;
Zookeeper注册中心: 基于分布式协调系统Zookeeper实现,采用Zookeeper的watch机制实现数据变更;
redis注册中心: 基于redis实现,采用key/Map存储,住key存储服务名和类型,Map中key存储服务URL,value服务过期时间。基于redis的发布/订阅模式通知数据变更;
Simple注册中心
14.Dubbo的注册中心集群挂掉,发布者和订阅者之间还能通信么?
可以的,启动dubbo时,消费者会从zookeeper拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。
15.Dubbo与Spring的关系?
Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
16.Dubbo使用的是什么通信框架?
默认使用NIO Netty框架。
17.Dubbo集群提供了哪些负载均衡策略?
Random LoadBalance: 随机选取提供者策略,有利于动态调整提供者权重。截面碰撞率高,调用次数越多,分布越均匀;
RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题;
LeastActive LoadBalance: 最少活跃调用策略,解决慢提供者接收更少的请求;
ConstantHash LoadBalance: 一致性Hash策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动;缺省时为Random随机调用。
18.Dubbo的集群容错方案有哪些?
Failover Cluster:失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。
Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2” 来设置最大并行数。
Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。
19.Dubbo的默认集群容错方案?Failover Cluster。
20.
20.Dubbo支持哪些序列化方式?
默认使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。
21.Dubbo超时时间怎样设置?
Dubbo超时时间设置有两种方式:
服务提供者端设置超时时间,在Dubbo的用户文档中,推荐如果能在服务端多配置就尽量多配置,因为服务提供者比消费者更清楚自己提供的服务特性。
服务消费者端设置超时时间,如果在消费者端设置了超时时间,以消费者端为主,即优先级更高。因为服务调用方设置超时时间控制性更灵活。如果消费方超时,服务端线程不会定制,会产生警告。
22.服务调用超时问题怎么解决?
dubbo在调用服务不成功时,默认是会重试两次的。
23.Dubbo在安全机制方面是如何解决?
Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方。
24.dubbo 和 dubbox 之间的区别?
dubbox 基于 dubbo 上做了一些扩展,如加了服务可 restful 调用,更新了开源组件等。
25.除了Dubbo还有哪些分布式框架?
大家熟知的就是Spring cloud,当然国外也有类似的多个框架。
26.Dubbo和Spring Cloud的关系?
Dubbo 是 SOA 时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而 Spring Cloud 诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了 Spirng、Spirng Boot 的优势之上,两个框架在开始目标就不一致,Dubbo 定位服务治理、Spirng Cloud 是一个生态。
8、Quartz定时任务
8.1导入时间表达式工具
说明:将课前资料中的Quartz项目导入项目,之后执行Main.java展现表达式工具
该工具是时间表达式生成器.用于定时任务.
8.2业务需求
说明:如果用户提交了订单.在30分钟之内没有完成支付,则将订单的状态由1改为6.
8.3定时任务Quartz
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.3.0。
1. 调度器 负责任务管理.内部有时钟监控
2. 触发器 当调度器需要执行任务时,通过触发器启动新的线程去执行.
3. JOB/JobDetail 定义任务.
8.4定时任务配置
引入jar包
编辑配置类
@Configuration
public class OrderQuartzConfig {
//定义任务详情
@Bean
public JobDetail orderjobDetail() {
//指定job的名称和持久化保存任务
return JobBuilder
.newJob(OrderQuartz.class)
.withIdentity(“orderQuartz”)
.storeDurably()
.build();
}
//定义触发器
@Bean
public Trigger orderTrigger() {
/SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(1) //定义时间周期
.repeatForever();/
CronScheduleBuilder scheduleBuilder
= CronScheduleBuilder.cronSchedule(“0 0/1 ?”);
return TriggerBuilder
.newTrigger()
.forJob(orderjobDetail())
.withIdentity(“orderQuartz”)
.withSchedule(scheduleBuilder).build();
}
}
编辑定时任务类
//准备订单定时任务
@Component
public class OrderQuartz extends QuartzJobBean{
@Autowired
private OrderMapper orderMapper;
/**
业务思想:
用户30分钟内,没有支付则将状态改为6交易关闭
sql:
update tb_order set status = 6,
updated=#{date}
where status=1 and created
/
//当程序执行时 执行该方法
@Override
@Transactional
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
Calendar calendar = Calendar.getInstance(); //获取当前时间
calendar.add(Calendar.MINUTE, -30);
Date timeOutDate = calendar.getTime();
Order order = new Order();
order.setStatus(6).setUpdated(new Date());
UpdateWrapper
updateWrapper.eq(“status”, 1)
.lt(“created”, timeOutDate);
orderMapper.update(order, updateWrapper);
System.*out
}
}