nginx_锁_同步_异步_阻塞

nginx 的相关介绍

nginx的产生:

首先是因为apache局限性而产生的nginx
apache当年最大的最流行的WEB服务器,发展时期相当的长;
也有很多的优点: 稳定;开源;跨平台等;
它最初的额设计就是一个重量级的服务器;缺点就是不支持高并发;
如果运行的访问量过高就会导致服务器卡死;进行进程和线程的操作也会导致CPU的资源过高;
导致HTTP的请求的响应的速度降低

所以不能成为高性能的服务器;这也决定了 nginx的诞生大的必要性;

nginx使用基于事件的驱动架构,使得它可以支持数以百万级别的TCP的链接
高度的模块和软件的自由的许可

nginx是一个跨平台的服务武器
还有就是极大的稳定性

关于nginx代理:

分为两种:

  1. 正向代理:

  2. 反向代理:

正向代理: nginx代理的是客户端 知道服务器大的ip地址 不知道客户端的IP地址

反向代理: nginx代理的是服务端 知道客户端的是谁;不知道服务器的具体IP地址

服务器的iP地址 用的私有的IP地址

使用nginx的公网IP地址做代理进行转发:

反向代理的最大的目的就是为了做负载均衡;由于对网站的访问压力;企业会采用部署多台服务器来缓解压力; 此时nginx机会实现负载均衡为每个服务器按照算法分发任务;从而降低链接压力;保证网站的正常运行;

乐观锁与悲观锁:

乐观锁对应于生活中乐观的人总是想着事情往好的方向发展:

而对于悲观锁就是对应生活中悲观的人总是想着事情往坏处发展:

这两种场景各有优缺点,不能根据场景去设定一个好一个坏;

悲观锁:

一中最坏的设想; 每次去数据库里面拿数据的时候总是会想别人会对数据进行修改;然后去拿数据的时候就会上锁;

这样别人想拿数据就会阻塞一值等待。知道阻塞解除,自己拿到锁;然后下一个需要数据的人,又会进行等待

共享资源每次只有一个线程在用,其他线程阻塞;用完之后再释放锁;把资源转让给其他进程使用;

传统的关系型数据库里面就用到了这种锁的机制;

乐观锁:

总是假设是最好的情况;每次去拿数据的时候都不会认为别人会修改数据 ;所以也就不会进行上锁;

但是再更新的时候会判断以下在此期间别人有没有对数据进行更新修改;

实现的方式:

第一个:在商品里面添加一个字段; 时间戳; 当用户去拿数据的时候 会先进行校验;看这个时间戳是不是已知的;如果是已知的就证明没有被修改;更新数据;

第二个: 在商品表里面加冗余的字段;商品的版本信息: 当用户去拿数据的时候,就会去校验;将版本进行对比;如果版本一致;则认为没有修改;更新数据

第三个; 添加商品库存的字段;

乐观锁使用于多读的应用类型;这样可以提高吞吐量;

两种锁的使用场景: 象乐观锁适用于写比较少的情况下;多读的场景;即冲突比真的比较少的时候这样就省去了锁的开销;加大了系统的整个吞吐量;

像悲观锁一般适用于多写的场景;因为多写的情况下一般容易产生冲突;这样就会导致上层应用不断的retry;这样反倒是降低了性能。

CAS算法: 比较与交换;是一种有名的无锁算法;即不使用锁的情况下对多线程之间实现变量的同步;也就是在没有线程阻塞的情况下实现变量的同步;所以也叫非阻塞同步;

分布式缓存Redis之管道 Pipline:

由于网络的延迟就算服务端有很强的数据处理能力;也会由于收到客户端的消息少;而造成吞吐量少;当客户端使用管道发送消息的时候;redis能够将部分请求放到队列中(使用内存);
执行完毕之后一次性发送结果;即打包发送;如果发送结果比较多的话;建议对返回的结果加标签;当然会造成内存空间的使用; 所以不是打包的数据越多越好。

所以管道充当的角色 一般就是 打包;批出理;在一定程度上提升了性能, 在一定程度上减少了TCp链接的交互往返的时间。

由于通信会有网络延迟,假如client和server之间的包传输时间需要0.125秒。那么上面的三个命令6个报文至少需要0.75秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显然没有充分利用 redis的处理能力。

而管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回,pipeline通过减少客户端与redis的通信次数来实现降低往返延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。 Pipeline 的默认的同步的个数为53个,也就是说arges中累加到53条数据时会把数据提交。其过程如下图所示:client可以将三个命令放到一个tcp报文一起发送,server则可以将三条命令的处理结果放到一个tcp报文返回。

需要注意到是用 pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。具体多少合适需要根据具体情况测试。

python中同步和异步–阻塞和非阻塞:

同步:

简单说;同步就是调用者调用了 一个任务一个功能时,调用者要等待被调用者将任务执行完毕之后,无论被调用者是阻塞还是非阻塞状态;必须等待被调用者执行完毕才能继续自己的任务。

异步

异步和同步是相对的,调用在发出之后;这个调用就直接返回了;所以没有返回结果;当一个异步任务的功能和任务发出之后,即使调用者不能立刻得到结果,这个时候被调用者可以去执行下面的代码;而不是一味的等待。

当异步执里面的被调用者执行完;调用者如何知道吗???:

当该异步任务完成之后;被调用者可以通过状态,通知或回调来通知调用者

如果异步使用-状态-来通知调用者;那么调用者就要每隔一段时间检查一次,这样的效率很低;

如果使用的是通知的方式那么效率就会很高; 因为异步功能几乎不需要做额外的操作;

阻塞和非阻塞:

阻塞调用指的是当前调用的结果返回之前;当前的线程会被挂起;(如果遇到IO操作);调用线程只有在得到结果之后才会被返回;函数只有在得到结果之后才会将阻塞的线程激活;

非阻塞和阻塞的概念是像对应的;非阻塞指的是在不能立刻得到调用结果之前也会立刻返回;同时该函数不会立刻阻塞当前线程。

总结

同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起一个函数(任务)调用的时候,一直等到函数(任务)完成,而进程继续处于激活(非阻塞)状态。而异步情况下是当一个进程发起一个函数(任务)调用的时候,不会等函数返回,而是继续往下执行,当函数返回的时候通过状态、通知、事件等方式通知进程任务完成。
阻塞与非阻塞针对的是进程或线程:阻塞是当请求不能满足的时候就将进程挂起,而非阻塞则不会阻塞当前进程

猜你喜欢

转载自blog.csdn.net/weixin_44090435/article/details/87860618