Internet 互联网技术生态圈和应用场景
互联技术学习Checklist
Level 1, Just read doc; 2. 知道架构设计,应用场景,用法,优缺点;3. 开过技术分享会,写过博客; 3. 写出使用它的个人应用程序;4. 实际项目中使用过,调试过; 5. 向这个项目做过贡献。6. 写过这个项目的介绍书籍。
- Memcached OK. Level: 1.
- Disruptor OK. Leve: 1
- Redis NO.
- Kafaka NO.
- Spark NO.
- MongoDB NO.
- ZeroMQ OK Level: 1
- Hadoop NO. 这种大的项目要细分. HBase: NO. HDFS: NO.
互联网后端的基本逻辑
互联网用户量大,所以要scale-out, 所以需要集群,所以需要集群管理工具
集群管理工具
问题导向: 互联网后台所要解决的问题或者说需求是什么
- 大量集群的管理,监控,修复,上线或者部署新功能,上线新机器
- 集群的伸缩,如何更好地增加或者移除机器,负载均衡
- 如何从大规模集群中获取数据(这其实就是大数据的一种问题),互联网天生地数据量大。
- 如何容错,集群中出现多台机器的挂机,如何不影响服务,如何能够恢复。
- 如何追踪一条数据在数据中心的流转轨迹。
- 互联网的计数器,功能,很常见,很基础。
基本概念
常见问题
- 如何设计秒杀系统?
http://zxcpro.github.io/blog/2015/07/27/gao-bing-fa-miao-sha-xi-tong-de-she-ji/
http://www.infoq.com/cn/articles/yhd-11-11-queuing-system-design
http://www.infoq.com/cn/articles/flash-deal-architecture-optimization
https://my.oschina.net/xianggao/blog/524943
http://blog.jobbole.com/99463/
http://mm.fancymore.com/reading/java-interview-project-killsgood.html
基本概念
应用场景
- 实时性
框架或者工具的基本维度
典型应用场景
为了解决什么问题
工具的作者
生态圈是否成熟
产品是否成熟
开发语言
Redis
开发语言:ANSI C
基本目标: 在内存存储数据,并能很灵活地访问数据
基本分类: 基于内存(但可以持久化到磁盘)的键值对数据库
定义:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.
It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs
and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions
and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic
partitioning with Redis Cluster.
应用场景:
缓存(数据库缓存,会话缓存,全页缓存)
消息队列
排行榜
计数器
相关介绍:
- http://www.infoq.com/cn/articles/tq-why-choose-redis
- 网络IO模型
- 内存管理方面
- 数据一致性问题
- 存储方式及其他方面
- 关于不同语言客户端的支持
Gemfire (金融领域)
- Java
- http://www.jianshu.com/p/ae2b23ca7535 (四星资料) 额外心得:项目规模的不同采用不同的架构,也是杀鸡用鸡刀,杀牛用牛刀,当然也考虑,鸡成长为牛的可能性。
Disruptor:
学习开源框架的基本方式,
- 听说这个产品后,查看官方资料,如果不错,直接看官网资料,否则,去看看第三方的中文,英文资料。
- 看中文资料,快速入门。(用时最多半小时)中文资料就是个大概,中文资料的质量一般,有时候会让你云里雾里。
- 看外文资料,外文资料,有时候会长篇大论,很费脑力,如果找不到,很好的介绍资料,直接看官网资料。半小时。
- 输出:基本搞清楚,为什么有这个产品?产品是什么?属于什么类的产品?关键特性是什么?谁做出来的?
- 通读官方资料,依据项目大小决定用时。如果官方资料不错,可以直接读官网资料,效率更快。(已浏览完:https://github.com/LMAX-Exchange/disruptor/wiki)
- 有个简单入门之后,写个Demo,搭环境。
- 看看源码和测试。(看源码之前必须读官方文档)
- 和其他类似产品和技术的比较,对当前产品有个更清楚的定位。
- 输出:从使用者的角度,搞清楚,如何使用,使用场景,优缺点,坑在哪里。缺点CPU磨损严重。
- 输出:从开发者的角度,搞清楚设计理念,核心技术和产品架构,能够给别人讲清楚。
- 输出: 写个简书,最终的输出形式。
- 看资料是要带着那两个视角:使用者,开发者。
- 再写一个如何学习某些工具? Git, 完美的工具是直接用起来,慢慢掌握,不过Git不是。
- 开发者角度,产品的解决方案的思路:不抛弃多线程,只是把多线程中,拖慢速度的东西给替换掉,锁->内存屏障+CAS, 而Akka虽然不是同级别的东西,Akka完全抛弃掉线程的模型,直接使用Actor模型,虽然底层还是要用到线程。
官方资料读后所获:(读完必写,要不然白读)
- SingleProduer is more fast than MutlipleProducer. (Basic Tuning Options)
- 没有牺牲一致性来获得高性能。FAQ
- 严格的FIFO. FAQ
- 多个同类型消费者的情况下,如何保证消息只被消费一次?给消费者编号(0-n-1), 在消费的时候,对Sequence号取模。(Basic Tuning Options)
- 如何配置 RingBuffer的大小?消息要能Fit in L3 Cache,根据实际环境的Cache未命中率来调。讲的不清楚。(Basic Tuning Options)
- 在消费者一端,有三种线程的等待策略。与之相关的三个因素,CPU usage, Latency, 部署的环境(core个数,超线程)。三种策略主要是在使劲耗CPU(Spin),还是不Spin, 用重量级的锁(带来延时的增长),之间权衡。 三种策略的延时排序(由大到小):SleepWait > YieldWait > BusySpinWait. (Basic Tuning Options). log system适合用YieldWait
是什么,著名用户
Disruptor是一个Java库,提供了高性能的线程间的消息传递。(也就是说是在同一个Java进程里,不同线程的数据交换手段)。主要特点是非阻塞算法。目前,log4j2和storm使用了这个库。
如下是来自官方的定义:https://github.com/LMAX-Exchange/disruptor/wiki
The LMAX Disruptor is a high performance inter-thread messaging library.
It grew out of LMAX's research into concurrency, performance and non-blocking algorithms and
today forms a core part of their Exchange's infrastructure.
设计理念和应用场景:
源于交易系统,交易系统要求低延时,高吞吐,所以disruptor主要面向性能的Java库。而性能就是要压榨CPU, Cache, Memory,
所以,Disruptor的设计就是尽可能消除会拖慢lantency的因素: Java GC,锁, Cache失效。为了消除GC影响,所以是用了数组,而不是常见的基于链表的形式;为了Cache失效,也就是伪共享,
设计理念和应用场景,如果你的应用是Pipeline结构,且要求低延时,高并发,就可以考虑这个库。
架构是怎样的。
- http://wiki.jikexueyuan.com/project/disruptor-getting-started/lmax-framework.html
- https://github.com/LMAX-Exchange/disruptor/wiki/Performance-Results
- https://zhuanlan.zhihu.com/p/23863915
- http://blog.sina.com.cn/s/blog_68ffc7a4010150yl.html
- https://martinfowler.com/articles/lmax.html
- http://nikgrozev.com/2015/07/14/overview-of-modern-concurrency-and-parallelism-concepts/
- http://java-is-the-new-c.blogspot.com/2014/01/comparision-of-different-concurrency.html
- http://nikgrozev.com/2015/07/14/overview-of-modern-concurrency-and-parallelism-concepts/
按目标分的一些资料
FailOver
存储系统
- MongoDB: https://www.mongodb.com/
- Redis: https://redis.io/
- Memached: https://memcached.org/
存储系统-缓存系统
缓存系统的产品
- EHCache (可以作为我的切入点)
缓存技术的基本知识
架构设计技术: 用Write Through/Read Through, 还是用Cache Aside; 同时,是否考虑读写分离。
读写策略:Write-Through, Write-Around, Write-Back and so on.
- http://www.alachisoft.com/resources/articles/readthru-writethru-writebehind.html
- http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained
- http://docs.oracle.com/cd/E13924\_01/coh.340/e13819/readthrough.htm
- https://vladmihalcea.com/2015/04/20/a-beginners-guide-to-cache-synchronization-strategies/
读写分离:
消息系统:
应用场景:
数据缓冲、
异步通信、
消息通信
汇集日志、
系统解耦
流量削峰
数据流转,分发
具体场景分析:
产品对比
- 二星资料: http://www.cnblogs.com/haochuang/p/5181583.html
- 二星资料: http://www.mrhaoting.com/?p=139
- 二星资料: http://kaimingwan.com/post/kafka/kafka-rabbitmq-activemq-zeromqhe-rocketmqdui-bijiao
ZeroMQ
Kafka
消息系统入门,概论
这东西太重要了,是我们整个系统数据流转的核心。我们使用了比较小众的一个消息队列,建议使用kafaka之类的。我们看看它的作用
- 服务之间的数据衔接
- 服务之间的缓冲
- 基于之上的各种应用,比如计数器
服务之间的数据衔接
系统一大了,服务就非常多,数据会在各个服务之间流动和加工。通常,数据不是单线路流动的,而是会开叉的,会流向到不同系统,最后或者消亡,或者进入数据持久层。这个时候我们希望有一种东西,能够衔接这些。
举个简单例子,当用户浏览了一篇博文,我们会做什么?
- JS会上报该数据到日志服务器
- Nginx会将数据落地,然后定时同步到集群上
- Nginx会将数据发往日志服务上
- 日志服务会将数据投递到消息队列
- ETL,我们假设配置了五条链路(假设名称为A-E),也就是我们对同一条数据进行五种不同的处理,我们看到,数据流在这里开叉了
- 每个链路实际上消费同一条消息
- A处理完后将数据再次投递到消息队列K,B处理完后投递到消息队列K1
- 资源中心会向K要A处理完的数据,索引服务会向K1要数据构建索引
- 还有更多操作。。。。。
我们看到,通过消息队列可以很好的衔接各个服务,让他们井然有序的处理数据。
服务之间的缓冲
假设没有消息队列,A直接将处理完的数据发给B,那么B会很忐忑,我不能挂掉,因为一旦挂掉,可能就造成数据丢失了。我也不能重启,因为重启的也可能会导致丢失几秒的数据。B还要时刻注意A的产能如何,产能如果过高,会压垮自己的。同样,为了解决这个问题,A也很蛋疼,它需要做重试机制,如果B没有反应过来,我需要判定B到底有没有接受到我的数据,总之很麻烦。
消息队列有效的解决了这些麻烦,A处理完直接把数据丢到消息队列中,B根据自己的系统情况尽量去消费。如果重启或者僵死了,下次依然可以记住上次消费的位置,接着消费就行。
不要小看这一点,对于一个快速成长的系统,不断的发布新版本是很正常的,这个时候就不能出现上面的问题。
基于之上的各种应用,比如计数器
计数器我后面会讲,它对服务的监控异常重要,简单而有效。比如我发现最近B系统接受数据有异常,这个时候我想还原数据怎么办,可都被B消费了呀。我们可以再起一个系统去消费B消费的主题,就能还原出数据了。还有数据流跟踪。一条数据经过N个系统流转,每个系统的每个模块都会把对这条数据的处理流程上报给消息队列,后端有个服务去消费这个消息队列,然后将数据存储到HBase中,接着做个前端展示,就可以完整的跟踪到一条数据的流转情况了。
而且,一般消息队列都是集群模式,非常稳定,你可以认为这是一个可靠的服务。基于一个可靠的服务去做事,就好比有了基石。
所以,我强烈建议,对于小团队,如果有多个服务,并且他们之间有交互(非查询性质的),那么最好是引入。