后端好书阅读与推荐(续五)

后端好书阅读与推荐系列文章:
后端好书阅读与推荐
后端好书阅读与推荐(续)
后端好书阅读与推荐(续二)
后端好书阅读与推荐(续三)
后端好书阅读与推荐(续四)
后端好书阅读与推荐(续五)html

Redis设计与实现

Redis设计与实现 (豆瓣): https://book.douban.com/subje...前端

经过前面这本书咱们已经知道redis怎么用比较好了,如今咱们来看看 Redis 的实现原理。这本书是做者本身看着源码写出来的,不得不佩服做者的智慧与毅力。这本书基于redis3.0,此刻redis最新版是4.0.9,咱们看书的时候能够本身去看看源码,看看redis有啥变化没,源码在此java

亮点:node

  • redis并无用C语言的字符串做为其基准字符串表示,而是使用了SDS(简单动态字符串)这一抽象类型,被用于键、字符串的表示,还有AOF中的缓冲区、客户端输出缓冲区等buffer的表示。 SDS的优点在于:记录了长度信息不须要遍历(空间换时间)、有长度因此会先检查空间是否足够而不会溢出、记录了free(未使用空间)长度从而避免频繁的内存从新分配(实现了空间预分配和惰性释放)、二进制安全等等
  • redis还定义了链表Linkedlist(用于实现List结构、发布订阅、慢查询、监视器等功能)、字典Dict(基于两个hash表,一个平时用、一个rehash用,主要用于实现数据库、Hash结构,须要注意渐进式rehash而不是java中Hashmap的一次性rehash,渐进式主要是避免键数量太大致使服务器暂时中止服务)、跳跃表SkipList(用于实现SortedSet结构、集群节点)、整数集合(用于实现Set结构)、压缩列表(用于实现ListHash结构,主要是面向小整数和短字符串,能够节省空间)、对象redisObject(redis的五种数据结构就是五种对象,key value都是对象,是对前面全部数据结构的一种封装,实现类型判断、编码、引用计数与对象共享和内存回收、过时删除等功能)等数据结构来实现特定功能
  • redis服务器是一个redisServer数据结构,包含一个redisDb的链表,每个数据库都是一个数据结构redisDb,中间有一个dict的数据结构保存了这个数据库全部的键值对,叫作键空间(key space)。键空间会维护命中次数、最后使用时间、过时清除、键监视、键空间(关注键自己)/键事件(关注操做自己如del、sadd、set等)通知等事件。此外还有一个clients字段保存了全部客户端
  • redisDb有一个dict类型的链表expire,保存了全部键的过时时间。过时键有三种删除策略:定时删除,设置timer,过时当即删除,对内存友好,可是浪费CPU时间片,并且大量的timer也不现实;惰性删除,听任无论,获取的时候检查是否过时,过时再删除,会浪费必定的内存,可是节省CPU时间;按期删除,每隔一段时间就检查过时键并删除,须要好好设计执行时长与频率。redis实际使用的是后二者
  • 持久化分为AOFRDB。RDB能够手动执行也可按期执行(BGSAVE)用内存数据生成压缩过的二进制RDB文件,SAVE命令会阻塞服务器,而BGSAVE会fork一个子进程来建立RDB文件,因此期间新的数据变化是不能提现到RDB文件中的,此外,RDB文件的载入是服务器启动自动完成的;AOF不直接记录数据,而是记录每个redis命令,分为append、文件写入(可能在系统缓冲中)、文件同步sync(强制刷到磁盘)三个步骤,文件同步有三种选项always(写入文件就刷盘)、everysec(默认)、no(由操做系统决定什么时候刷盘)
  • redis是一个事件驱动的程序,这种程序通常会有一个相似于while(true)的无限循环,叫作事件循环,每一个循环里服务器要处理两种事件:文件事件,完成网络通讯(基于Reactor模式);时间事件,完成定时、周期操做之类。
  • Sentinel(哨兵)是redis的高可用解决方案,由>=1个Sentinel实例监视任意多的redis主服务器以及所属的从服务器(从服务器复制主服务器的数据),完成主备切换等功能。实现原理是Sentinel每隔10秒就向全部主服务器发送info命令,获取各个主服务器及其对应的从服务器的信息,而后也会以相同形式给从服务器发送info命令。另外会以两秒一次的频率向全部主从服务器发送一个publish的命令,而后会subscribe这个频道,这样就能得到每一个服务器的相关信息了。Sentinel之间只有命令链接,没有频道链接。
  • 在线检测经过每秒的ping来实现,当超过一个Sentinel的时限down-after-milliseconds还没得到一个服务器的回复这个Sentinel就认为此服务器主观下线,而后会询问其余Sentinel,若是超过quorumSentinel都认为此服务器主观下线那么这些Sentinel就认为这个服务器就客观下线了。当一个主服务器下线时,Sentinel们会选举一个领头SentinelRaft leader选举)来对这个服务器群进行主备切换,具体算法就不说了
  • redis集群经过槽指派实现,全部数据分配到16284个槽,全部槽都有节点处理时集群才能对外服务,每一个节点能够处理多个槽(一个节点能够是主从服务器群,提升该节点可用性),当一个节点收到命令发现该槽不在本节点时会向客户端返回重定向指令,让其请求对应的节点。从新分槽能够在线分,由redis-trib实现。
  • redis 支持慢查询,超过showlog-log-slower-than选项执行时间的命令会被记录到慢查询日志,日志采用保存最近的,数量由slowlog-max-len决定。

本书配合着官方文档来学习是最佳的,文档在此中文文档mysql

MySQL技术内幕

MySQL技术内幕 (豆瓣): https://book.douban.com/subje...linux

经过前面这本书咱们已经知道 mysql 怎么用比较好了,如今咱们来看看 mysql 的实现原理。nginx

亮点:git

  • mysql采用单进程多线程模式。逻辑上,采用了分层可插拔架构,上层是链接池管理模块,中层是语句解析、缓存、优化模块,下层是可插拔的存储引擎如myisam、Innodb(存储引擎基于表而不是数据库),下层依赖于操做系统层面的文件系统
  • InnoDB支持事务、行锁、外键,主要面向在线事务处理应用(OLTP),经过MVVC提升并发性,默承认重复读级别使用 next-key locking避免幻读,此外还提供插入缓冲、二次写、自适应hash索引、预读等高性能与高可用功能;MyISAM不支持事务与行锁,可是支持全文索引,主要面向OLAP应用;NDB是一个集群引擎,数据所有在内存因此速度很快,可是链接操做不是在引擎层面解决的,效率较低;Memory也是内存存储的引擎,适合临时表存储中间结果使用,默认使用hash索引,只支持表锁;Archive只支持insert和select,支持压缩适合存储归档数据;还有太多不经常使用的,就不一一列举了
  • innodb采用多线程模型,Master Thread负责将缓冲池中的数据异步刷新到磁盘,保证数据一致性,包括脏页刷新,合并插入缓冲,undo页回收;IO thread负责写操做AIO的回调处理;Purge Thread 负责undo log的回收,减轻Master Thread的负担;Page cleanner Thread 负责脏页刷新,减轻master thread 负担
  • mysql经过写缓冲WAL将随机写改为了顺序写提升了吞吐量,同时保证数据持久性,若是宕机就会用redoundo两阶段的日志来将数据恢复到数据库文件中。可是mysql基本页面通常是16KB,而操做系统基本页面通常是4KB,若是在写入到数据库文件时发生宕机,就可能引发partial write问题,亦即一个mysql页面只写入了一部分,这时就要依靠double write:同步缓冲区数据时,不是直接写入文件,而是写入内存中的double write buffer再调用fsync写到共享表空间文件,而后立刻调用fsync同步至数据库文件,这样若是发生了partial write,就能够去共享表空间找到该页副本并复制到数据库文件中,而后再进行redo,undo。固然,若是文件系统自己有防范机制就没必要启用double write
  • InnodB中页是管理数据库的最小磁盘单位,分为多个部分,其中Fileheader、Pageheader、FileTrailer(检查完整性)是固定的,记录一些该页的信息如checksum、页所在B+树层数。userrecords、freespace、pagedirectory(页相对位置,B+索引只记录一条数据所在页,真正查找还需把这一页加载如内存,靠二分搜索这一条记录)是实际的行记录存储空间,所以大小是动态的。
  • Cardinality能帮助咱们决策是否须要创建索引,能够经过show index来观察,通常好比性别这个字段Cardinality就很低,由于可能一个类型female就占据了全部行的一半,根本不必创建索引,而名字这个字段Cardinality就很高,适合创建索引(固然也得是应用经常按名字检索,这样才有必要创建索引)
  • Innodb1.2.x 开始支持全文检索,并支持myisam引擎全部功能。全文检索通常经过倒排索引实现,亦即存储每个词汇及其对应文档,这样关键词检索时就能迅速返回相应文档
  • 事务分为几种:扁平事务,全部操做位于同一层次,要么都提交要么都回滚(也就是说不支持部分回滚),是应用程序成为原子操做的基本模块;带有保存点的扁平事务,在扁平事务基础上支持部分回滚,用保存点(volatile,易失的)实现;链事务,事务的连接;嵌套事务,顶层事务管理多个子事务;分布式事务,一般是在分布式场景下运行的扁平事务
  • 事务的实现主要依靠:程序员

    • redo实现持久性,亦即commit操做必须将专门的redo日志文件fsync刷新到磁盘才能返回成功,合并多条语句插入优于一句一句插入也是由于减小了日志刷盘频率,因为redolog块与磁盘扇区块大小一致,因此无需doublewrite
    • undo实现回滚操做和MVCC,是存在于数据库内部共享表空间的一个特殊段(undo段)中的逻辑日志,记录了事务执行的反效果便于回滚,MVCC的实现是经过若某行记录已被其余事物占用,当前事务能够经过undo日志获得改行以前版本的信息,需注意undolog也会产生redolog,亦即undolog也须要持久性维护;
    • purge最终完成deleteupdate操做,由于Innodb支持MVCC,因此记录不能在提交时当即处理,purge操做判断合什么时候真正清理数据并回收undo page,具体来讲,若是一行数据不被真正引用那就可清理deleteupdate数据了;
    • group commit将多个事务的数据一次性调用fsync刷新到磁盘减小刷盘次数;
    • 须要注意的是binlog,用来实现Point-In-Time的恢复以及主从复制的实现,很是相似于redolog,可是二者本质有很大不一样:redolog产生于下层只针对Innodb引擎产生,是物理格式日志,记录针对每一页的修改,事务过程当中不断被写入;binlog产生于中层,针对任何引擎都会产生,是逻辑日志,记录针对每条SQL语句,事务提交后一次写入
  • Mysql经过XA事务来保证分布式的一致性,同时内部也有XA的使用,如如今数据库为了复制通常都是打开binlog的,事务提交时既要写binlog也要写redolog,这就会涉及原子性问题,亦即两个日志必须同时写入,经过先作prepare操做,将事务的xid写入,而后写入binlog,而后提交存储引擎并写入redolog

深刻Linux内核架构

深刻Linux内核架构 (豆瓣): https://book.douban.com/subje...github

这是一本能把linux内核全貌展示给咱们的大部头,涵盖了包括进程管理,内存管理、锁与通讯、设备驱动、文件系统等等。要采起观其大略,用时细读的策略,去宏观的把握linux的设计哲学。

亮点:

  • 操做系统架构主要涉及两种类型:微内核,最基本的功能由中央内核实现,其余功能委托给一些进程实现,经过通讯接口与中心内核通讯,这种模型研究活跃可是实用性进展甚微;宏(单)内核,内核的所有代码打包到一个文件中,内核中每一个函数均可以访问其余部分,目前性能强于微内核,linux也是使用这种模式,可是linux模块化作得很好(能够动态添加减小功能,内核文件也不会膨胀),也消除了单内核的一个重要弱点
  • linux虚拟地址空间是每一个进程管理自身资源与其余进程隔离的工具,与物理内存无直接关系(由CPU访问总线数决定),分为内核空间(task-size~最高位)和用户空间(0~task-size),这样就为全部进程提供了一个统一的系统视图,无需计较其余进程;Intel处理器有4中特权级别,可是linux只使用两种不一样的状态:核心态和用户态,用户态进程禁止直接访问内核空间(这是内核的专用领域)的数据和执行其代码,用户态进程只能借助于系统调用或者中断来陷入内核态,由内核代为执行操做。物理内存基本单位是页框页帧),虚拟内存基本单位是,二者大小同样,对应关系由页表(linux采用4级页表)决定
  • 建立进程有两种方式,fork(父子进程只有PID不一样,使用COW使得fork更高效,亦即子进程只复制页表,只有父子某一进程要向内存写入数据时才真正复制物理内存,若只读则能够共享而没必要复制,这样就延迟甚至消除了了大量的复制,节约了内存和CPU时间)和exec(将一个新程序加载到当前内存中执行,旧的程序内存页将刷出)。linux使用clone建立线程(或者说轻量级进程),相似于fork,可是能精确检查哪些资源与父进程共享哪些为线程独立建立
  • Linux的进程调度分为两大部分:调度策略和上下文切换。非实时进程的调度策略通常考虑公平性,linux全部可运行进程都在一个红黑树中排序,vruntime(一次调度间隔的虚拟运行时间实际运行时间*(NICE_0_LOAD/权重nice值))最小的进程位于左下方会被调度器优先考虑,休眠进程被放入等待队列中,唤醒后会从新被加入红黑树。实时进程是指该进程必须在指定的时间内完成好比飞机飞行控制指令,于是通常都有相对非实时进程较高的优先级,不一样于非实时进程调度
  • 物理内存管理分为两个层次:伙伴系统负责物理页帧的管理,围绕多页组成的连续内存块的拆分与合并,新进的内核引入了反碎片技术(可移动页与可移动内存区)防止物理内存碎片发生;slab负责处理小块内存的分配,并提供了用户层malloc函数族的内核等价物。
  • Linux使用了SystemV(Unix的一个分支)引入的机制来支持用户进程间通讯(IPC)与同步。主要经过信号量、消息队列、共享内存三种方式实现。此外,linux还有其余IPC机制如信号(kill -s)、管道(以虚拟文件系统实现,适用于父子进程单向通讯)及命名管道(适用于无关系的进程间通讯)、socket(更通用,可多主机进程通讯)
  • Linux内核为了统一文件访问接口,在用户进程(或者C标准库)和文件系统(Ext2/3,XFS,Reiserfs)之间引入抽象层:虚拟文件系统(VFS)。文件系统通常分为3种:基于磁盘的FS(如Ext2/3),无持久FS(如/proc),网络文件系统。处理文件时,用户程序关注一个整型的文件描述符fd(由内核分配,只在一个进程内有效,两个进程即便有相同的fd也是指向不一样的文件),而内核关注的是inode,包含了一个文件/目录的元数据但不含文件名(文件名只是inode的别称)。软链接采用文件名指向的方式,独立inode;硬连接采用引用计数,共享inode
  • 无持久FS有:proc标准挂载点是/proc,其信息不能从块设备读取,只有在读取文件内容时才动态生成相关信息,也能够在不从新编译内核源码的状况下修改内核行为,与内核通讯,包含网络信息、内存管理、进程特征数据、文件系统、设备驱动、电源、终端、系统控制参数;sysfs的标准挂载点是/sys,是一个向用户空间导出内核对象的文件系统,提供了查看和修改内核数据结构的能力;用于专门目的的小文件系统
  • 应用程序看到的内核是一个执行多种系统功能(内存管理、系统资源请求、访问外设、进程通讯、读取文件等)的大的例程集合,标准库是一个中间层,用于在不一样的体系结构和系统间,标准化并简化内核例程的管理

同窗们,堪称整个现代互联网软件基石的Linux内核源码就在这里,有没有勇气去瞅瞅?
还有这本书更精简,推荐给不想看太多源码和细节的同窗: Linux内核设计与实现(原书第3版)

Kafka权威指南

Kafka权威指南 (豆瓣): https://book.douban.com/subje...

Kafka是一个高吞吐量的分布式(支持分区partition、多副本replica、使用zookeeper协调)消息系统,目前普遍用来进行实时大数据处理如:hadoop批处理、storm/Spark流式处理引擎,web日志、消息队列等等,因此做为一个后端开发者,颇有必要了解一下。我想的是把kafka做为消息队列的表明进行学习,未来若是要用ActiveMQ、RabbitMQ、ZeroMQ、RocketMQ等或者要本身要开发一个MQ均可以触类旁通或者进行借鉴。

亮点:

  • Kafka是一个流平台,容许发布和订阅数据流,能够看作传统的MQ,可是有不少不一样点:支持多生产者,多消费者,另外多个消费者还能够组成群组,共享一个消息流而且特定消息整个群组只消费一次;以集群方式运行,可伸缩,还有MirrorMaker支持不统集群之间的复制;数据能够持久化,相似于数据库,保证消息必定送达;流式处理使得你能够用不多的代码就能动态的处理派生流和数据集。也能够看作实时版的Hadoop(大数据中,Hadoop主要应用于批处理与数据分析,Kafka因为低延迟更适合业务应用,可以在业务事件发生时及时做出响应,为业务运营提供支撑,好比商品浏览数据转换为商品推荐)。也能够看作ETL,可是并不是简单移动数据而是面向实时数据流。这三个方面是Kafka的主要特性
  • 生产者产生一个ProducerRecord对象,包含Topicvalue,还可能有key或者partition,对象序列化后发送到分区器上,若是有partition则不操做,若无则根据key来指定partition(partition的设计目的是取消消息大小限制和提升并行度)。选好partition后发往对应的topic和partition的记录批次,这一批记录等待一次性的发往对应的broker(因此批的大小影响延迟和吞吐量),整个过程有失败自动重试功能,超过必定次数返回客户端异常。生产者经过设置ack=n,能够保证一个ProducerRecord有n个副本(一个Partition的全部副本中有一个Leader负责与客户端交互,其他副本做为Follower从Leader复制数据,提供容错性)被写入成功才会收到成功的ack消息。整个topic的顺序没法保证,1个分区的顺序能够经过设置retries>0(重试次数),和max.in.flight.requests.per.connection=1(1次只发1条消息避免后到的消息先成功)来保证,不过会严重影响生产者性能,若非严格顺序要求不建议使用
  • 一个消费者group老是能得到一个topic的所有消息无论还有没有其余group订阅该topic,group内经过添加消费者来伸缩读取能力和处理能力,每一个消费者只处理一部分数据,并且消费者数量不要超过partition数量,否则多余的会闲置浪费。group内全部消费者向群组协调器发送心跳保持活跃,添加和删除消费者时的再均衡(分配分区与消费者对应关系)也是由群组协调器完成
  • Kafka使用ZooKeeper维护集群成员信息,全部broker都对应/brokers/ids的临时节点并订阅其变动事件,在broker加入或退出时获得消息;集群中有一个控制器对应/controller临时节点(全部broker均可以尝试建立节点成功则成为Controller,失败则知道Controller已经存在,全部broker都会监听这个节点的变动,经过递增的controller epoch来忽略旧控制器消息避免脑裂),除了完成broker功能以外还负责partition副本的leader选举;持续获得来自leader最新消息的副本叫作同步的副本,当leader失效时,只有同步的副本才可能被选为新的leader;不一样partition的副本和leader都均匀的分布在全部broker之间避免热点问题,副本尽可能放在不一样机架提升容错性
  • kafka处理常见几种请求:元数据请求,能够发送给任意broker,包含客户端感兴趣的主题列表,返回主题包含的分区、副本及其leader;生产请求,ack能够为0,1,all三个值;读取请求,零拷贝返回客户端指定的消息(省掉了用户缓冲区,直接从磁盘到内核),要注意的是,leader只有把数据安全复制到副本中才能给客户端返回这个数据;其余请求,如偏移量(再也不保存在ZooKeeper中)
  • 由于大文件的查找和删除都很费时易错,因此每一个partition都分红了许多segment,一个segment包含1GB或者1周的数据(较小为准),正在写入数据的叫作活跃片断,永远不会被删除。每一个分区还有一个索引提高查询效率
  • 可靠性和速度(简便性)一般是负相关的,Kafka在这二者之间是能够高度配置的,适应从跟踪用户点击支付操做的不一样可靠性级别要求。kafka的可靠性机制包括:分区消息顺序性、多副本确认实现容错性、只要还有一个副本是活跃的已提交消息就不会丢失、消费者只能消费已提交数据。这些基本机制加上一些配置参数(unclean.leader.election.enable、min.insync.replicas、生产者ack)的权衡就能构建不一样级别的可靠系统,可靠级别能够是针对broker或者topic。总而言之、可靠性不只是kafka单方面的事情,须要整个系统配合如系统架构、生产者消费者的使用方式与配置、topic和broker配置等等
  • 跨集群的复制在kafka中叫作mirror功能,应用场景:将不一样区域的集群数据复制到中心集群便于分析数据、冗余实现灾备、云迁移。跨数据中心通讯有高延迟、有限带宽、高成本等特色,常见架构有:Hub-Spoke架构(一中央多本地集群)、双活架构(两个集群都对外服务,就近原则)、主备架构(主集群服务、备集群只在主不可用时对外服务)
  • 事件流是无边界的(持续增加)、有序的、可重播的、不可变的记录。流式处理就是实时的处理一个或多个事件流,是一种编程范式就像请求响应式批处理式,可是延迟吞吐量都位于二者之间。

看完这本书基本就能把kafka的使用方法和基本原理搞清楚了,可是翻译有时候有点点问题,我以为普通的段落能够翻译,可是专用名词如segmentpartition等仍是直接保留比较好,省得有歧义,固然总体上来来讲配合官网文档读起来仍是没问题的。
要想深刻的话源码在

NoSQL精粹

NoSQL精粹 (豆瓣): https://book.douban.com/subje...

本书先分析了传统关系数据库的不足而后引入NoSQL,讲到了键值、文档、列族、图等多种数据库并分析了其优点劣势,可让咱们对NoSQL有一个全面的了解,为咱们进一步NoSQL的探索之路开一个好头。

亮点:

  • NoSQL泛指最近诞生非关系型数据库如Cassandra、MongoDB、Neo4j等,他们主张无模式(schemaless)的数据。传统关系数据库有可持久化模型标准便于共享和集成事务支持等优势,NoSQL有无模式便于程序对象与数据库之间的映射适应集群等优势。因此NoSQL和传统关系数据库各有所长,发展过程当中也在互相借鉴优势,谁也不能取代谁,未来都会在各自的领域中发光发热
  • 关系模型把数据分割成简单的行,一般一个对象可能须要多行数据经过外键链接在一块儿来表示(若是按照严格的关系数据库范式);聚合是领域驱动设计的术语,把一组相关联的对象视为一个总体单元来操做,这个单元就叫作聚合(aggregate)。聚合的边界划分没有标准答案,取决于你以后准备怎样操做数据。由于以聚合为单位复制和分片比较天然因此集群中操做数据库仍是聚合更简单。若数据操做大多在同一聚合内执行则应使用面向聚合的数据库(键值、文档、列族数据库),若交互须要多种不一样的格式则最好选聚合无知式aggregate-ignorant)数据库(关系数据库、图数据库),若待处理数据中有大量的关系最好就选关系数据库,可是若是关系复杂、并行交错最好选图数据库(插入费时、查询比复杂的join快得多)
  • 宽泛的说数据分布有两条正交的路径:复制,一份数据拷贝到多个节点,有主从式(主节点瓶颈问题)和对等式(一致性问题)两种形式;分片,将不一样的数据存放到不一样的节点。这里注意不要和另外一个概念混淆:数据库水平(一个表的不一样行数据置于不一样节点)、垂直(一个表的不一样列置于不一样节点或者拆为多个表)拆分。实际分布式系统中通常都是复制和分片结合的(如上面提到的kafka)
  • 版本戳能够检测冲突用来实现CAS,能够用计数器、GUID、Hash、时间戳等方式实现也能够组合实现,分布式系统中,能够采用“由版本戳构成的数组”来检测不一样节点是否发生了“相互冲突的更新操做”
  • 键值数据库最简单,只能按键检索,适用于会话信息、用户配置信息、购物车等;文档数据库呈树状结构能够看作支持值检索的键值数据库,适用于CMS及博客、电子商务等;列族数据库将数据存在列族中,列族里的行则把许多列数据与本行的行键联系起来,列族一般把须要一并访问的相关数据分红组,提升访问效率,适用于事件记录、博客、计数器等;图数据库把具备属性的实体(节点)按关系(边)联系起来,适用于互联网数据如社交网络、安排运输线、推荐引擎等
  • Neal Ford 2006年造出了多语言编程(polyglot programming):应该以多种语言混合编写同一应用程序,以各自语言的优点来解决其中不一样的问题,同理数据库也能够遵循相似的原则混合持久化(polyglot persistence),好比购物车能够用键值数据库存储,可是订单要用关系型数据库。因此除非是编程语言狂热爱好者,咱们大部分人都不该该去争论什么语言好,什么数据库好,不要想着一把刷子走遍世界,而应该普遍了解,解决问题的时候选择合适的工具,必要的时候也要本身改工具甚至造工具

本书的一个问题就是有点旧了,2013年第一版,这5年来NoSQL发展很快,已经被普遍用于企业级的系统之中了,尤为是Redis和MongoDB,因此有需求就大胆的用吧。

大型网站技术架构

大型网站技术架构 (豆瓣): https://book.douban.com/subje...

把事情作大是咱们许多人的追求,这本书就可让咱们了解一下一个大型网站的架构应该要注意些什么,不管是摸得着的tech仍是比较摸不着的leadership,都值得借鉴。固然,书很薄,大多只能泛泛而谈,要想真正掌握,每一部分咱们都得本身单独深挖,因此本书能够看作一个大目录,为接下来的学习指引方向。

亮点:

  • 讲述了一个单机网站发展到大型分布式网站的完整历程,处于业务快速发展期间的公司能够借鉴,提早作好规划
  • 架构设计时要注意:不要盲目追随大公司而是要考虑本身业务;要结合网站实际使用新技术,不要盲目追求新奇酷炫;不要想着用技术解决一切问题,业务模式等也须要考虑;
  • 模式:每个模式描述了一个在咱们周围不断重复的问题以及该问题解决方案的核心,这样你就能1次又1次的使用该方案而没必要重复劳动。模式的关键在于可重复性,包括问题和方案的可重复性。
  • 大型网站有一些常见的架构模式:分层,如应用层、服务层、数据层;分割,如购物、论坛、搜索、广告;分布式,包括服务、静态资源、数据库、计算、锁、文件、配置信息等;集群,相同业务经过集群负载均衡提升服务能力;缓存,如CDN、反向代理、本地缓存、分布式缓存;异步,事务关系越少就越能独立发展,异步也是解耦的一种协做方式;冗余,冷备、热备、灾备等;自动化,包括发布、测试、部署、报警、失效转移、恢复、降级、分配资源等,自动化能提升效率并减少人为出错几率;安全,手机验证码、图像验证码、转义、风控等。全部模式都是在性能(响应时间、qps等)、可用性(冗余)、伸缩性(机器的增减)、扩展性(业务的增减)、安全性(恶意访问、窃取、攻击)这几个维度之间进行平衡
  • 性能针对不一样群体须要不一样的定义(针对用户的响应时间,针对系统的吞吐量、并发量等)来衡量,也须要测试(压测等),同时要从架构的多个层面(前端、应用层、存储层)来进行优化
  • 可用性通常用几个9来形容(4个9就是99.99%,一年小于53分钟不可用),实现高可用架构的主要手段是数据和服务的冗余备份和失效转移。应用层(文库、贴吧、知道)和服务层(帐户服务、session服务)由于通常无状态因此很容易扩展(负载均衡),新节点上下线都很容易,可是服务层须要注意好分级管理、超时设置、异步调用、服务降级、幂等设计等。数据层(数据库、文件、缓存)为了保证数据不丢失须要复制并均匀分布在集群中
  • 集群处理能力若是能和服务器数量正相关,那么网站就具备伸缩性架构,若是能成线性关系那更是高伸缩性,主要分为不一样服务物理拆分和单一服务集群伸缩(类比于数据库垂直拆分和水平拆分)。应用集群伸缩性通常经过负载均衡实现如http重定向、DNS轮询、反向代理、IP负载均衡、数据链路层负载均衡等;缓存集群伸缩性仅靠负载均衡是不够的,还须要一致性hash、虚拟槽分区等方法使得缓存在节点发生变化时不会集体失效;存储集群伸缩性对持久性和可用性要求更高,可是这里做者没怎么讲具体作法
  • 扩展性是在对现有系统影响最小的状况下持续提高或增长服务的能力,表如今系统基础设施稳定,应用之间耦合较少等,是系统架构层面的开闭原则体现。主要有:分布式消息队列解耦生产者与消费者、分布式服务打造可复用的业务平台、利用开放平台打造生态圈实现开放双赢等方式
  • 安全性通常主要注意XSS、注入、CSRF等攻击,主要手段有:用户输入转义、表单token、验证码、加密、过滤、风控等
  • 领导的真谛就是寻找一个值得共同奋斗的目标,营造一个让你们都能最大限度发挥自我价值的氛围;发掘人的优秀比发掘优秀的人更有意义

读完发现本书几乎全程“黑友商”,有的甚至好几遍(* ̄︶ ̄),有点不纯粹啊。

深刻理解 Java 内存模型

这本书是infoq上的系列博客造成的一本很薄的书,对于了解JMM仍是颇有用的。
深刻理解Java内存模型(二)——重排序: http://www.infoq.com/cn/artic...

亮点:

  • 重排序的目的是提升性能,分为三种:编译器、处理器指令级并行技术、内存系统的重排序。JMM属于语言级别的内存模型,经过禁止特定类型的编译器重排序(直接可控)和处理器重排序(经过内存屏障实现)来在不一样的平台对为程序员提供一致的内存模型
  • 内存屏障有四种:StoreLoad的排列 ,其中StoreLoad Barriers是一个全能型的屏障,同时具备其余三个屏障的效果,它确保store数据对其余处理器的load可见
  • 处理器内存是硬件级别的内存模型,JMM是一个语言级别的内存模型,顺序一致性内存是一个理论参考模型,性能依次下降,可编程性依次上升。因此JMM主要关注易编程性和性能,在二者之间求得平衡

深刻分布式缓存:从原理到实践

深刻分布式缓存:从原理到实践 (豆瓣): https://book.douban.com/subje...

缓存在现在的互联网中已经几乎是标配了,分布式缓存更是大型网站不可或缺的,本书就让咱们从原理开源实现业务实践一块儿打包了解了。

亮点:

  • 计算机世界中,不管是硬件仍是软件,不管是单机仍是分布式,缓存都被用于解决响应缓慢的问题,是提高性能的关键技术。其核心就是空间换时间,解耦高速部件与低速部件。缓存因为不一样硬件的访问速度和价格不一样而进行分级,每一级存储对应热度级别的数据,分层逐级减小流量的冲击,保护用户体验与系统可用性。分布式环境下要关注其命中、更新、失效、一致性等
  • 缓存是无所不在的,从架构的角度看能够分为三块:客户端缓存 在客户端减小网络请求,如页面缓存(文件化)、浏览器经过HTTP协议实现的缓存(etag,304 not-modified)、APP缓存(sqlite)等;网络缓存 位于客户端与服务端之间,代理部分客户端请求给服务端减负,如web代理缓存(nginx)、边缘缓存(CDN);服务端缓存 是缓存的重点和难点,如数据库缓存(query_cache)、平台级缓存(大而全的Ehcache、极简的Guava )、应用级缓存(redis)
  • 书中澄清了许多分布式方面的概念和理论,如集群是一组互相独立的计算机经过网络链接构成一个组实现同一个功能,对客户端表现为一个独立服务器,能够增长可用性与伸缩性,而分布式系统就是许多不一样功能的集群构成的一个实现特定业务的系统;幂等性是指调用1次和N次结果同样,这个在分布式系统中很重要是由于网络抖动等因素经常致使重发;分布式系统的本质是一堆廉价的硬件攒在一块儿得到更好的吞吐量和性能以及可用性,有几个问题广泛关心:活性检测(周期心跳、累计失效检测)、高可用(主备、双主、集群)、容错处理(冷热切换、冗余、备份)、重试机制(失败重试、事务补偿)、负载均衡(多机分担请求),也有几个实践很重要:全局ID(数据库自增id如flicker、UUID、snowflake、预生成置于缓存中)、哈希取模分配一致性哈希(单调性、分散性)、路由表数据拆分
  • 书中在JSR规范下带领咱们实现了一个缓存框架CSCache,架构由上到下是客户端、缓存提供层、缓存管理层、缓存存储层(基本存储,LRU存储,Weak存储),设计思路值得借鉴
  • redis有瓶颈:单机数据量限制、单线程吞吐量限制(尤为是大块数据读取延迟明显)、单点故障等,目前已有的解决方案有:水平拆分如Proxy和Twemproxy、自带主从复制(含断点续传)、sentinel监控自动故障转移(使用raft相似算法选主)、redis3.0后出来的去中心化(采用Gossip协议在节点之间达成一致)的cluster提供了完整的sharding、replication、failover等解决方案
  • 本书覆盖了广告、社交、电商等多种业务的缓存模式,能开开眼界,未来可能还真用得上,尤为是社交和电商这两块讲得很细致,几乎能够做为一精简而完整的解决方案了
相关文章
相关标签/搜索