1.什么是Lucene?
作为一个开放源代码项目,Lucene从问世之后,引发了开放源代码社群的巨大反响,程序员们不仅使用它构建具体的全文检索应用,而且将之集成到各种系统软件中去,以及构建Web应用,甚至某些商业软件也采用了Lucene作为其内部全文检索子系统的核心。apache软件基金会的网站使用了Lucene作为全文检索的引擎,IBM的开源软件eclipse的2.1版本中也采用了Lucene作为帮助子系统的全文索引引擎,相应的IBM的商业软件Web Sphere中也采用了Lucene。Lucene以其开放源代码的特性、优异的索引结构、良好的系统架构获得了越来越多的应用。
Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
(2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
(3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度 ...
(0) Reactor模型
Reactor模型是一种经典的线程模型,一般分为三种类型:
Reactor单线程模型
Reactor多线程模型
Reactor主从多线程模型
Reactor单线程模型
Reactor单线程模型是指所有的IO操作包括acceptor操作和handler操作都由一个线程完成;
Netty中Reactor单线程的实现
1234ServerBootstrap b = new ServerBootstrap();EventLoopGroup group = new NioEventLoopGroup(1); //创建只有一个线程的线程池b.group(group); //acceptor操作和handler操作共用group线程池中的一个线程;
单线程模型适用在小容量,低并发的应用场景上,对于高负载高并发的应用场景不适用:
如果handler操作是计算密集型操作,在高并发情况下即便CPU负荷达到100%也可能完成不了海量数据的处理,这就可能造成消息堆积和延迟处理;
如果handler操作中出现阻塞则可能会导致acceptor操 ...
之前做爬虫时,在公司设计开发了一个通用的垂直爬虫平台,后来在公司做了内部的技术分享,这篇文章把整个爬虫平台的设计思路整理了一下,分享给大家。
写一个爬虫很简单,写一个可持续稳定运行的爬虫也不难,但如何构建一个通用化的垂直爬虫平台?
这篇文章,我就来和你分享一下,一个通用垂直爬虫平台的构建思路。
爬虫简介首先介绍一下,什么是爬虫?
搜索引擎是这样定义的:
网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取网页信息的程序或者脚本。
很简单,爬虫就是指定规则自动采集数据的程序脚本,目的在于拿到想要的数据。
而爬虫主要分为两大类:
通用爬虫(搜索引擎)
垂直爬虫(特定领域)
由于第一类的开发成本较高,所以只有搜索引擎公司在做,如谷歌、百度等。
而大多数企业在做的都是第二类,成本低、数据价值高。
例如一家做电商的公司只需要电商领域有价值的数据,那开发一个只采集电商领域数据的爬虫平台,意义较大。
我要和你分享的主要是针对第二类,垂直爬虫平台的设计思路。
如何写爬虫首先,从最简单的开始,我们先了解一下如何写一个爬虫?
简单爬虫开发爬虫最快的语言一般是 Python ...
引言书接上文,前面我们分别介绍了 Dubbo 的设计思想,分析了微内核的实现方案,服务导出与引入、以及集群容错方面的代码。经过前文的铺垫,本篇文章我们终于可以分析服务调用过程了。
技术内幕实现细节服务调用过程在前面的文章中,我们分析了 Dubbo SPI、服务导出与引入、以及集群容错方面的代码。经过前文的铺垫,本篇文章我们终于可以分析服务调用过程了。Dubbo 服务调用过程比较复杂,包含众多步骤,比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发以及响应请求等步骤。接下来我们将会重点分析请求的发送与接收、编解码、线程派发以及响应的发送与接收等过程。
首先服务消费者通过代理对象 Proxy 发起远程调用,接着通过网络客户端 Client 将编码后的请求发送给服务提供方的网络层上,也就是 Server。Server 在收到请求后,首先要做的事情是对数据包进行解码。然后将解码后的请求发送至分发器 Dispatcher,再由分发器将请求派发到指定的线程池上,最后由线程池调用具体的服务。这就是一个远程调用请求的发送与接收过程。至于响应的发送与接收过程,这张图中没有表现出来。对于这两 ...
一、Future模式Java 1.5开始,提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
Future接口可以构建异步应用,是多线程开发中常见的设计模式。
当我们需要调用一个函数方法时。如果这个函数执行很慢,那么我们就要进行等待。但有时候,我们可能并不急着要结果。
因此,我们可以让被调用者立即返回,让他在后台慢慢处理这个请求。对于调用者来说,则可以先处理一些其他任务,在真正需要数据的场合再去尝试获取需要的数据。
1、Callable与Runnablejava.lang.Runnable是一个接口,在它里面只声明了一个run()方法,run返回值是void,任务执行完毕后无法返回任何结果
123public interface Runnable { public abstract void run();}
Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法叫做call(),这是一个泛型接口,call()函数返回的类型就是传递进来的V类型
123public in ...
数据结构
未读翻译自http://www.h2database.com/html/mvstore.html
转载请著名出处,及译者信息。
第一次翻译,诸多不妥请谅解,谢谢。
概述MVStore是一个持久化的、日志结构式的kv存储。本计划用它作为H2的下一代存储子系统,但你也可以在一个不涉及JDBC或者SQL的应用中直接使用它。
MVStore代表多版本存储。
每一个store包含大量的map,这些map可以用java.util.Map接口存取。
支持基于文件存储和基于内存的操作。
它希望更快,更简单的使用,更小。
支持并发读写操作。
支持事务(包括并发事务与两阶段提交(2-phase commit))
模块化的工具,支持插拔式的数据类型定义、序列化实现,支持插拔式的存储载体(存到文件里、存到堆外内存),插拔式的映射实现(B-tree,R-tree,当前用的concurrent B-tree),BLOB存储,文件系统层的抽象以使其支持文件的加密与压缩
示例代码1234567891011121314import org.h2.mvstore.*;// open the store (in-memor ...
在之前的一个系列的文章里,我们从基本原理开始,一步步实现了基于 Vector Trie 的持久化 List 数据结构。 接下来将要研究的是使用 HAMT 这一数据结构实现持久化 Hash Table。
持久化数据结构简介 这篇文章里, 我们对比各种可以用来实现持久化数据结构的方案,详细介绍了 Vector Trie 这种数据结构,说明了用它实现 List 优势。 HAMT 的全称是 Hash Array Mapped Trie,它和 Vector Trie 一样,都利用了前缀树(Trie)这种数据结构作为底层数据结构, 但是由于 Map 本身和 List 之间性质的差别,HAMT 在很多方面进行了特别的处理。接下来我们先从原始 Hash Table 数据结构谈起, 逐步引出 HAMT 的设计原理。
Hash TableHash Table 是利用对象的 Hash 值对所储存的键进行散列从而实现快速的插入、删除和访问的数据结构。 在 Go 语言中的 map、Java 中的 HashTable 和 HashMap 和 Python 当中的 dict 都是 HashTable 的一种。 其基 ...
Reactor模式一、Web请求处理架构概述在处理Web请求时,主要存在两种体系结构:thread - based architecture(基于线程)和event - driven architecture(事件驱动)。
(一)Thread - based Architecture(基于线程)
基于线程的体系结构通常采用多线程方式来处理客户端请求。每当接收到一个请求,就会开启一个独立的线程进行处理。这种方式在直观上易于理解,但存在一定局限性。每个线程都需要占用一定的内存资源,并且操作系统在线程之间切换时会产生开销。当并发访问量不大时,这种开销可能不明显,但随着线程数量增多,会显著降低Web服务器的性能。此外,当线程处理I/O操作并处于等待输入状态时,线程处于空闲状态,这期间会造成CPU资源的浪费。以下是其典型设计流程:
客户端发起请求。
服务器接收请求后,在单独的线程中进行读取(read)操作。
对读取的数据进行解码(decode)。
调用相应的处理程序(handler)进行业务逻辑处理,如计算(Compute)。
对处理结果进行编码(encode)。
最后将响应发送(s ...
MySQL死锁产生原因所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。mysql如何避免死锁https://www.pianshen.com/article/7970964764/
11 、死锁的概念
是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,事务都将无法推进下去,解决死锁的最简单问题是不要有等待,任何的等待都转换为回滚,并且事务重新开始,但在线上环境,这可能会导致并发性能下降,甚至任何一个事务都不能进行,而这所带来的问题远比死锁的问题更严重
解决死锁的问题最简单的一种方法是超时,当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务回滚,另一个等待的事务就能继续运行了, ...
redis
未读Redis 主从在线切换记录
背景Redis master 所在实例主机需要下线维护. 如何切换主从对线上影响最小. 当前架构如下图
技术方案方案1引入 redis sentinel.
步骤:
部署redis sentinel
修改业务配置, 修改业务代码.
kill master.
check
建立新主从逻辑
优点:
切换简单, kill 主库即可, sentinel 可自动提升 slave -> master.
缺点:
需要部署 redis sentinel, 新的中间件.
需要改动业务代码.
方案2直接切换
步骤:
使从库可写, redis-cli -h redis-slave -p 6379 CONFIG set slave-read-only no
修改业务侧配置, redis 地址指向可写的 slave 实例, 重启业务应用
确保主从同步完成, 停止主从同步. redis-cli -h redis-slave -p 6379 slaveof no one
建立新主从逻辑.
优点:
符合直觉
没有代码改动
缺点:
如果切换过程中有问题, 需要及时回滚配置和业 ...

