Netty之所以这么火,与它的巨大优点是密不可分的,大致可以总结如下:
· API使用简单,开发门槛低。· 功能强大,预置了多种编解码功能,支持多种主流协议。
· 定制能力强,可以通过ChannelHandler对通信框架进行灵活扩展。· 性能高,与其他业界主流的NIO框架对比,Netty的综合性能最优。
· 成熟、稳定,Netty修复了已经发现的所有JDK NIO中的BUG,业务开发人员不需要再为NIO的BUG而烦恼。
· 社区活跃,版本迭代周期短,发现的BUG可以被及时修复。
Redis的主要应用场景:缓存(数据查询、短连接、新闻内容、商品内容等)、分布式会话(Session)、聊天室的在线好友列表、任务队列(秒杀、抢购、12306等)、应用排行榜、访问统计、数据过期处理(可以精确到毫秒)。
相对于其他的键-值对(Key-Value)内存数据库(如Memcached)而言,Redis具有如下特点:
(1)速度快 不需要等待磁盘的IO,在内存之间进行的数据存储和查询,速度非常快。当然,缓存的数据总量不能太大,因为受到物理内存空间大小的限制。
(2)丰富的数据结构 除了string之外,还有list、hash、set、sortedset,一共五种类型。
(3)单线程,避免了线程切换和锁机制的性能消耗。
(4)可持久化 支持RDB与AOF两种方式,将内存中的数据写入外部的物理存储设备。
(5)支持发布/订阅。
(6)支持Lua脚本。
(7)支持分布式锁 在分布式系统中,如果不同的节点需要访同到一个资源,往往需要通过互斥机制来防止彼此干扰,并且保证数据的一致性。在这种情况下,需要使用到分布式锁。分布式锁和Java的锁用于实现不同线程之间的同步访问,原理上是类似的。
(8)支持原子操作和事务Redis事务是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。如果命令在运行期间出现错误,不会自动回滚。
(9)支持主-从(Master-Slave)复制与高可用(Redis Sentinel)集群(3.0版本以上)
(10)支持管道Redis管道是指客户端可以将多个命令一次性发送到服务器,然后由服务器一次性返回所有结果。管道技术的优点是:在批量执行命令的应用场景中,可以大大减少网络传输的开销,提高性能。
ZooKeeper的核心优势是,实现了分布式环境的数据一致性,简单地说:每时每刻我们访问ZooKeeper的树结构时,不同的节点返回的数据都是一致的。也就是说,对ZooKeeper进行数据访问时,无论是什么时间,都不会引起脏读、重复读。
read系统调用,并不是直接从物理设备把数据读取到内存中;write系统调用,也不是直接把数据写入到物理设备。上层应用无论是调用操作系统的read,还是调用操作系统的write,都会涉及缓冲区。具体来说,调用操作系统的read,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。
有了内存缓冲区,上层应用使用read系统调用时,仅仅把数据从内核缓冲区复制到上层应用的缓冲区(进程缓冲区);上层应用使用write系统调用时,仅仅把数据从进程缓冲区复制到内核缓冲区中。
在Java服务器端,完成一次socket请求和响应,完整的流程如下:
· 客户端请求:Linux通过网卡读取客户端的请求数据,将数据读取到内核缓冲区。
· 获取请求数据:Java服务器通过read系统调用,从Linux内核缓冲区读取数据,再送入Java进程缓冲区。
· 服务器端业务处理:Java服务器在自己的用户空间中处理客户端的请求。
· 服务器端返回数据:Java服务器完成处理后,构建好的响应数据,将这些数据从用户缓冲区写入内核缓冲区。这里用到的是write系统调用。
· 发送给客户端:Linux内核通过网络IO,将内核缓冲区中的数据写入网卡,网卡通过底层的通信协议,会将数据发送给目标客户端。
阻塞IO,指的是需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作。阻塞指的是用户空间程序的执行状态。传统的IO模型都是同步阻塞IO。在Java中,默认创建的socket都是阻塞的
在Java应用程序进程中,默认情况下,所有的socket连接的IO操作都是同步阻塞IO(BlockingIO)
总之,阻塞IO的特点是:在内核进行IO执行的两个阶段,用户线程都被阻塞了。
阻塞IO的缺点是:一般情况下,会为每个连接配备一个独立的线程;反过来说,就是一个线程维护一个连接的IO操作。在并发量小的情况下,这样做没有什么问题。但是,当在高并发的应用场景下,需要大量的线程来维护大量的网络连接,内存、线程切换开销会非常巨大。因此,基本上阻塞IO模型在高并发应用场景下是不可用的。
异步IO模型的特点:在内核等待数据和复制数据的两个阶段,用户线程都不是阻塞的。用户线程需要接收内核的IO操作完成的事件,或者用户线程需要注册一个IO操作完成的回调函数。正因为如此,异步IO有的时候也被称为信号驱动IO。
对于高并发、高负载的应用,就必须要调整这个系统参数,以适应处理并发处理大量连接的应用场景。可以通过ulimit来设置这两个参数。方法如下:
ulimit -n 1000000000
在上面的命令中,n的设置值越大,可以打开的文件句柄数量就越大。建议以root用户来执行此命令。
终极解除Linux系统的最大文件打开数量的限制,可以通过编辑Linux的极限配置文件/etc/security/limits.conf来解决,修改此文件,加入如下内容:
soft nofile 1000000
hard nofile 1000000
soft nofile表示软性极限,hard nofile表示硬性极限。
如果想永久地把设置值保存下来,可以编辑/etc/rc.local开机启动文件,在文件中添加如下内容:
ulimit -SHn 1000000
网友评论