1. 分布式
分布式
:将同一套业务代码按照业务功能或者自定义的维度拆分不同的子系统,各个系统分开部署,每个子系统叫做服务,每个服务之间一般通过rpc或者webservice来调用。
优点
:分布式的好处就是解耦了原系统,从而便于运维部署和水平扩展,提供软件的伸缩性,甚至服务可以通过不同的语言来实现.各个模块交给不同的人员去开发,每个人各司其职,出现问题也可以快速定位
缺点
:分布式也并不是毫无缺点的,存在以下的问题
1.服务调用通过网络来调用,一般微服务之间使用rpc来调用的,而rpc的底层就是TCP协议,如果网络故障或者延迟高一点,那么服务调用就有出现超时的可能性
2.分布式在业务体量比较小或者粒度划分的情况下就是一种灾难式开发,开发和运维的成本都会直线上升
3.分布式的数据一致性和事务比较难以保障,业务目前使用最多的是两阶段提交2pc,需要本地事务和远程事务综合提交,性能比较差
4.布式session的维护在单体工程中是不需要考虑session的安全性的,而在分布式环境中就必须考虑如何去维护session的一致
5.分布式事务问题:分布式下如何保证各个服务的数据一致性也是一种挑战,当程序出现异常崩溃的时候能够保证各个服务能够正常回滚是很重要的。
分布式最常见的技术:分布式缓存、分布式存储、分布式计算、分布式静态资源
2. 集群
通过负载均衡,将同一套代码部署在多个后端服务器上,而多个服务器可以提供更多的cpu、内存、硬盘等资源,从而提升整理的处理请求能力。集群的每个服务器叫做节点,每个节点提供的是相同的服务,节点的关系只是一种简单的复制,具体是哪个节点处理,则是根据负载均衡策略来决定;在网站的处理能力出现下滑的时候,简单的在集群中增加服务器台数就可以显著增加整体的数据量处理能力(不过存在上限);
3. 缓存
缓存是提高软件的性能第一手段,最有效和最具代表性的方法,缓存分为单机缓存和分布式缓存。最常见的分布式缓存技术为redis、memorycache等,单机缓存比如hashmap、concurrentHashmap、guava等。单机缓存的承载容量有限,而分布式缓存的伸缩性和的存储容量会比较可观,就算缓存的空间不足了,也可以通过增加服务器来扩展。
缓存最显著的作用有两个:①加快数据的访问速度②分担后端的数据访问和存储的负载能力,保护数据库
使用缓存需要注意等几个点:
1. 缓存雪崩
缓存雪崩指的是所有的缓存在统一时间全部失效,导致大量的请求直接涌入数据库,数据库被击垮。
解决缓存雪崩的方法:缓存过期值在一定的基础上设置随机值。也就是说,不要给所有缓存都设置一样都过期时间,比如都设置10分钟过期,这样容易引发缓存雪崩问题。
2. 缓存击穿
缓存击穿是指某些热点key在某一时间全部失效了,导致大量的请求涌入后台DB数据库
解决缓存击穿的方法:热点数据设置永不过期
3. 缓存穿透
一直请求不存在的数据,最终走的还是数据库就是缓存穿透
解决缓存穿透的方法:(1)采用布隆过滤器(bloomFilter),布隆过滤会有一定的误差,但是可以晒选出一定不存在的数据,缺点是无法判定某个key是否确定存在。将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。(2)如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓存中获取就有值了,而不会继续访问数据库
缓存这边还有几个其它都概念
缓存预热
缓存预热就是系统上线后,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
缓存预热解决方案:(1)直接写个缓存刷新页面,上线时手工操作下;(2)数据量不大,可以在项目启动的时候自动进行加载;(3)定时刷新缓存;
缓存降级
当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
4. 队列
试想这样一个的高请求量场景:各大电商的双11,在双11的那一刻,有大量订单涌入,后端会接受请求,然后写入数据库,等待数据库的返回.如果请求量非常大的话,数据库读写IO就会阻塞,那么程序就会出现卡死,数据库崩溃等问题
如果采用队列的话,将下单请求发送到队列中,然后立刻返回(可以按照业务决定,比如返回处理中,等到真正成功再通知用户),这样就不需要等待后端必须返回成功。消费端可以按照请求的顺序平滑的去消费,缓解了高峰的请求,并且实现了请求下单和实现下单的解耦。从以下图可以看出使用队列以后处理起来比较平滑~
5. 多线程
多线程真正的意义有两个①提高cpu的利用率 ②:加快程序执行效率,目前已经是多核的时代,服务器六核、八核屡见不鲜,在多核的cpu中如果使用单线程那么无疑是对多核cpu的浪费,多线程能够有效提高cpu利用的效率,多个任务分给多个cpu去处理,可以实现真正的并行处理。如果在单核cpu中,只是cpu在不停的切换cpu时间。假设我们有十个表格的数据需要分析处理(计算密集型),采用单线程需要一个个的轮询表格,而多线程在合理分配线程数的情况下就可以同时处理,提高开发的效率
6. 限流
限流是面对高并发的利器之一,例如秒杀场景:在大量的请求涌入后台,QPS高达几十万,如果不能做到有效控制就可能导致请求击垮数据库,DB基本上是一个网站的命脉。缓存、队列、限流等方式的本质其实都是为了保护DB。限流的简单理解其实就是过滤掉无效的请求,将请求限制在一个可以控制的范围内,最常见的限流有以下方式:
1. Redis限流
Redis限流的基本思路是采用redis的key过期策略,将业务id和业务值放入到redis中设置一定的过期时间,等请求再次进入的时候,如果能从redis获取到值,那么我就因为是重复性请求。Redis过滤限流是最基础的限流手段,适用于过滤同一个用户请求的场景
2. 令牌桶算法
令牌桶算法的思路是在一定的时间内生成以固定的速度生成有限个令牌数量放入桶中,所有的请求首先从令牌桶中去尝试获取令牌,如果能获取到就可以继续执行,否则请求就会被抛弃。Google开源的guava中有RateLimter可以实现单机限流,令牌桶算法是限流非常有效的手段,
3. 漏桶算法
漏桶算法的基本原理是将请求直接存放在一个漏斗中,请求过多的话,那么就会漏斗就会溢出,溢出的请求则会被拒绝服务。漏桶算法可以控制端口的流量输出速率,平滑请求的突发流量,实现流量整形.
因为漏桶算法的漏出速率是有效的,因此漏桶算法相比于令牌桶算法有一个显著的缺点是无法应对突发性的流量.可令牌桶算法是可以的
4. nginx限流
使用参数来限制某一个ip的在时间范围内的访问频率
5. 客户端限流
发起请求按钮点击后,在后面的几秒内(由业务决定)设置为disabled,这一操作步骤虽然很小,但是带来的限流作用很可观
7. 服务降级和熔断
hystrix
8.安全性问题
1. sql注入
2. 跨域攻击
与主站的域名、端口、协议不一致性的请求都可以理解为跨域访问,浏览器有同源策略:浏览器会限制来自于不同源的documet和脚本对当前的document读取或设置部分属性,但是比如src\form表单提交\< img >\< iframe >\< link >是没有跨域限制的。
csrf攻击:登陆网站A,获取到了网站A的cookie用户信息,然后点击了一个恶意网站外链B,网站B可以利用csrf漏洞模拟A网站的用户信息去请求A的某些敏感接口,比如转账、发送消息、邮件、获取部分信息、发起恶意代码等。
如何防止csrf攻击:①接口请求加上随机的token值或者token约束的规则,或者是有时效性的token码。这样的话,外链去访问接口在拦截器中验证token是否有效,②在http的头部加入自定义参数:放到 HTTP 头中自定义的属性里。通过 Ajax,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中③减少使用get提交,get提交会降低门槛
3. XSS攻击
xss攻击指的是攻击者对包含有漏洞的服务器注入js代码,会诱使受害者打开攻击的服务器URL,其中里面的URL会包含一些恶意代码,比如植入病毒、添加广告片段代码、篡改接口信息等。
预防xss攻击的方法:对于用户提交的内容,需要过滤任何有执行能力的脚本或者影响页面的CSS,