1、 可重复读(Repeatable read):默认隔离机制,就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读的发生。
(1)这是MySQL的默认事务隔离级别
(2)它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
(3)此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
(4)InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题
2、读未提交(Read uncommitted),一个事务可以读取另一个未提交事务的数据,最低级别,任何情况都无法保证。
(1)所有事务都可以看到其他未提交事务的执行结果
(2)本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
(3)该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据
3、读已提交(Read committed),一个事务要等另一个事务提交后才能读取数据,可避免脏读的发生。
(1)这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
(2)它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
(3)这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。导致这种情况的原因可能有:(1)有一个交叉的事务有新的commit,导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit
4、串行(Serializable),是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。Mysql的默认隔离级别是Repeatable read。
(1)这是最高的隔离级别
(2)它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
(3)在这个级别,可能导致大量的超时现象和锁竞争
原文链接:https://blog.csdn.net/fuzhongmin05/article/details/91351933
nginx -s quit 优雅停止nginx,有连接时会等连接请求完成再杀死worker进程
nginx -s reload 优雅重启,并重新载入配置文件nginx.conf
nginx -s reopen 重新打开日志文件,一般用于切割日志
nginx -v 查看版本
nginx -t 检查nginx的配置文件
nginx -h 查看帮助信息
nginx -V 详细版本信息,包括编译参数
nginx -c filename 指定配置文件
你的业务代码和部署环境打包在一起,保证了各测试,预发,生产环境下的部署一致性,而且方便扩容
1.更高效的利用系统资源
2.更快速的启动时间
3.一致的运行环境
4.持续交付和部署
5.更轻松的迁移、扩容
##搜索仓库MySQL镜像 docker search mysql
##下载Redis官方最新镜像,相当于:docker pull redis:latest docker pull redis
##下载仓库所有Redis镜像 docker pull -a redis
##下载私人仓库镜像 docker pull bitnami/redis
首先就要说什么是中间件?我的理解是:
中间件是帮助应用程序与其他应用程序、网络、硬件、操作系统交互或通信的软件。
换句更简洁的话:「将具体业务和底层逻辑解耦的软件」。其实符合中间件的软件范畴非常宽,日常用的Redis、Nginx、Zookeeper、Memcached等等都是「中间件」。所谓的「中间」是相对于架构体系内的,它不涉及具体的业务逻辑也不涉及底层的硬件逻辑,用于用户数据交换和管理,能够起到「中介」的作用,这就是中间件。
数据库中间件
当项目很小的时候,直接使用编程语言下的数据库驱动操作数据库就可以了,有些开发会用ORM的方式操作数据库:这是够用的。
但随着业务发展,数据量和读写QPS越来越高,主从模式的MySQL实例压力越来越大,单纯的对服务器硬件升级已经无法满足生产环境的需要。在我司不成文的习惯是单表不要超过5千万条记录,数据库量大的时候就设计分库分表,也就是「分而治之」,把QPS和数据量分片限定在一个范围内。
当然还有很多其他相关的功能,如读写分离、路由策略、统计、管理、鉴权等等。这些是在业务逻辑之上的,不应该在业务代码中把这部分堆进去,应该抽象它们出来作为一个独立的组件,这就是数据库中间件。
Web框架中间件
一般Web框架都支持中间件,Web框架中间件的本质是插件系统,是一系列的框架钩子,在收到请求和返回响应这个过程里面去做一些额外的事情。中间件种类很多,举例一些:
响应压缩
记录日志
支持会话Session
CSRF保护
验证/身份鉴别
访问控制
资源使用检查(如内存占用)
请求指标
健康检查
静态资源管理 …
这些中间件将业务和非业务代码功能进行解耦:
框架里面可能内置了一些常用的中间件,也可能只是内置中间件支持。你可以配置使用某个(些),也能方便的自定义中间件
Web视图中不需要手写中间件逻辑,按约定好的用法框架会在对应的生命周期中按照约定的顺序去执行这些中间件逻辑
消息队列(Message Queue)
消息队列就是Message+Queue。其实消息可以说是一个数据传输单位,它包含了创建时间、通道/主题信息、输入参数等全部数据;队列(Queue)是一种FIFO(先进先出)的数据结构,编程语言一般都内置(内存中的)队列实现,可以作为进程间通讯(IPC)的方法。使用队列最常见的场景就是生产者/消费者模式:生产者生产消息放到队列中,消费者从队列里面获取消息消费。
消息代理(Message Broker)
消息代理是一种架构模式,用于消息验证、变换、路由。虽然不同的消息中间件架构和实现各不相同,但是大部分都实现了Broker:其实就是消息中间件服务器,它是中间件的核心。
Spring 中拦截器(Interceptor)与过滤器(Filter)的区别
拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
过滤器:是在javaweb中,你传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符.。
拦截器和过滤器比较
①拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。过滤器依赖与servlet容器。
③拦截器只能对action(也就是controller)请求起作用,而过滤器则可以对几乎所有的请求起作用,并且可以对请求的资源进行起作用,但是缺点是一个过滤器实例只能在容器初始化时调用一次。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑
实现登录状态保持的两种方法 cookie、session和token
第一种,cookie和session的配合使用
实现原理:当用户请求页面,一般需要先登录,用户第一次输入用户名和密码之后,前台发送post请求,后台获取用户信息,通过查询数据库来验证用户信息是否正确,如果验证通过,则会开辟一块session空间来储存用户数据,并且同时生成一个cookie字符串,由后台返回给前台,前台接收后,会把这个cookie字符串储存到浏览器的cookie空间中,这个cookie就相当于一把钥匙,可以打开后台存储对应用户信息的锁,当用户下一次请求的时候,客户端便会自动携带这个cookie去请求服务器,服务器识别后,就会读取session中的用户信息,这样用户就可以直接访问,就不需要再输入用户名密码来验证身份了。
优缺点: 优点是:提升了用户体验,cookie和session的结合使用,比直接在客户端保存用户信息要相对安全;缺点是:当服务器向浏览器传送cookie的时候,很容易被劫持,并不是绝对的安全,还有一点就是,在大型的项目中,服务器往往不只一台,如果第一次请求,用户信息被保存在了服务器1的session空间中,但是第二次请求被分流到了服务器2,这样就获取不到用户信息了,依然要重新登录,所以又引出了另一种方法:token来实现。
第二种,使用token安全令牌
实现原理:当用户请求页面,输入用户信息,服务端经过验证后,会生成一个token安全令牌(随机字符串),并返回给客户端,当客户端发送下一次请求的时候,直接携带这个token,服务端识别后,就可以直接访问页面,不需要再次登录了
优点:token只是以字符串的形式存在,不要服务器再开辟空间,并且相对更安全,即使在传输的过程中被劫持,别人也并不能破解内容,并且减少了服务器压力,减少频繁的查询数据库。
-Xmx
指定java程序的最大堆内存, 使用java -Xmx5000M -version判断当前系统能分配的最大堆内存
-Xms
指定最小堆内存, 通常设置成跟最大堆内存一样,减少GC
-Xmn
设置年轻代大小。整个堆大小=年轻代大小 + 年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss
指定线程的最大栈空间, 此参数决定了java函数调用的深度, 值越大调用深度越深, 若值太小则容易出栈溢出错误(StackOverflowError)
-XX:PermSize
指定方法区(永久区)的初始值,默认是物理内存的1/64, 在Java8永久区移除, 代之的是元数据区, 由-XX:MetaspaceSize指定
-XX:MaxPermSize
指定方法区的最大值, 默认是物理内存的1/4, 在java8中由-XX:MaxMetaspaceSize指定元数据区的大小
-XX:NewRatio=n
年老代与年轻代的比值,-XX:NewRatio=2, 表示年老代与年轻代的比值为2:1
-XX:SurvivorRatio=n
Eden区与Survivor区的大小比值,-XX:SurvivorRatio=8表示Eden区与Survivor区的大小比值是8:1:1,因为Survivor区有两个(from, to)