自从各种脱裤门事件开始层出不穷,在下就学乖了,各个地方的密码全都改成不一样的,重要帐号的密码定期更换,生怕被人社出祖宗十八代的我,甚至开始用起了假名字,我给自己起一新网名”兴才”,这个看起来还不错的名字,其实是我们家乡骂人土话,意思是脑残人士…. -_-|||额好吧,反正是假的,不要在意这些细节。
这只是名,至于姓氏么,每个帐号的注册资料那里,照着百家姓上赵钱孙李周吴郑王的依次往下排,什么张兴才、李兴才、王兴才……于是也不知道我这样”兴才”了多久,终于有一天,我接到一个陌生电话:您好,请问是马兴才先生吗?
好么,该来的终于还是来了,于是按名索骥,得知某某网站我用了这个名字,然后通过各种途径找,果然,那破站被脱裤子了。
果断Down了那个裤子,然后就一发不可收拾,走上了收藏裤子的不归路,直到有一天,我发现收藏已经非常丰富了,粗略估计得好几十亿条数据,拍脑袋一想,这不能光收藏啊,我也搭个社工库用吧……
0×01 介绍
社工库怎么搭呢,这种海量数据的东西,并不是简单的用mysql建个库,然后做个php查询select * from sgk where username like ‘%xxxxx%’这样就能完事的,也不是某些幼稚骚年想的随便找个4g内存,amd双核的破电脑就可以带起来的,上面这样的语句和系统配置,真要用于社工库查询,查一条记录恐怕得半小时。好在这个问题早就被一种叫做全文搜索引擎的东西解决了,更好的消息是,全文搜索引擎大部分都是开源的,不需要花钱。
目前网上已经搭建好的社工库,大部分是mysql+coreseek+php架构,coreseek基于sphinx,是一款优秀的全文搜索引擎,但缺点是比较轻量级,一旦数据量过数亿,就会有些力不从心,并且搭建集群做分布式性能并不理想,如果要考虑以后数据量越来越大的情况,还是得用其他方案,为此我使用了solr。
Solr的基础是著名的Lucene框架,基于java,通过jdbc接口可以导入各种数据库和各种格式的数据,非常适合开发企业级的海量数据搜索平台,并且提供完善的solr cloud集群功能,更重要的是,solr的数据查询完全基于http,可以通过简单的post参数,返回json,xml,php,python,ruby,csv等多种格式。
以前的solr,本质上是一组servlet,必须放进Tomcat才能运行,从solr5开始,它已经自带了jetty,配置的好,完全可以独立使用,并且应付大量并发请求,具体的架构我们后面会讲到,现在先来进行solr的安装配置。
0×02 安装和配置
以下是我整个搭建和测试过程所用的硬件和软件平台,本文所有内容均在此平台上完成:
软件配置: solr5.5,mysql5.7,jdk8,Tomcat8 Windows10/Ubuntu14.04 LTS
硬件配置: i7 4770k,16G DDR3,2T西数黑盘
2.1 mysql数据库
Mysql数据库的安装和配置我这里不再赘述,只提一点,对于社工库这种查询任务远远多于插入和更新的应用来说,最好还是使用MyISAM引擎。
搭建好数据库后,新建一个库,名为newsgk,然后创建一个表命名为b41sgk,结构如下:
id bigint 主键 自动增长
username varchar 用户名
email varchar 邮箱
password varchar 密码
salt varchar 密码中的盐或者第二密码
ip varchar ip、住址、电话等其他资料
site varchar 数据库的来源站点
接下来就是把收集的各种裤子全部导入这个表了,这里推荐使用navicat,它可以支持各种格式的导入,具体过程相当的枯燥乏味,需要很多的耐心,这里就不再废话了,列位看官自己去搞就是了,目前我初步导入的数据量大约是10亿条。
2.2 Solr的搭建和配置
首先下载solr:
$ wget http://mirrors.hust.edu.cn/apache/lucene/solr/5.5.0/solr-5.5.0.tgz
解压缩:
$ tar zxvf solr-5.5.0.tgz
安装jdk8:
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo apt-get install oracle-java8-set-default
因为是java跨平台的,Windows下和linux下solr是同一个压缩包,windows下jdk的安装这里不再说明。
进入解压缩后的solr文件夹的bin目录,solr.cmd和solr分别是windows和linux下的启动脚本:
因为社工库是海量大数据,而jvm默认只使用512m的内存,这远远不够,所以我们需要修改,打开solr.in.sh文件,找到这一行:
SOLR_HEAP=”512m”
依据你的数据量,把它修改成更高,我这里改成4G,改完保存. 在windows下略有不同,需要修改solr.in.cmd文件中的这一行:
set SOLR_JAVA_MEM=-Xms512m -Xmx512m
同样把两个512m都修改成4G。
Solr的启动,重启和停止命令分别是:
$ ./solr start
$ ./solr restart –p 8983
$ ./solr stop –all
在linux下还可以通过install_solr_service.sh脚本把solr安装为服务,开机后台自动运行。
Solr安装完成,现在我们需要从mysql导入数据,导入前,我们需要先创建一个core,core是solr的特有概念,每个core是一个查询、数据,、索引等的集合体,你可以把它想象成一个独立数据库,我们创建一个新core:
在solr-5.5.0/server/solr子目录下面建立一个新文件夹,命名为solr_mysql,这个是core的名称,在下面创建两个子目录conf和data,把solr-5.5.0/solr-5.5.0/example/example-DIH/solr/db/conf下面的所有文件全部拷贝到我们创建的conf目录中.接下来的配置主要涉及到三个文件, solrconfig.xml, schema.xml和db-data-config.xml。
首先打开db-data-config.xml,修改为以下内容:
<dataConfig>
<dataSource name="sgk" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/newsgk" user="root" password="password" batchSize="-1" />
<document name="mysgk">
<entity name="b41sgk" pk="id" query="select * from b41sgk">
<field column="id" name="id"/>
<field column="username" name="username"/>
<field column="email" name="email"/>
<field column="password" name="password"/>
<field column="salt" name="salt"/>
<field column="ip" name="ip"/>
<field column="site" name="site"/>
</entity>
</document>
</dataConfig>
这个文件是负责配置导入数据源的,请按照mysql实际的设置修改datasource的内容,下面entity的内容必须严格按照mysql中社工库表的结构填写,列名要和数据库中的完全一样。
然后打开solrconfig.xml,先找到这一段:
<schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
把它全部注释掉,加上一行,改成这样:
<!-- <schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>-->
<schemaFactory class="ClassicIndexSchemaFactory"/>
这是因为solr5 以上默认使用managed-schema管理schema,需要更改为可以手动修改。
然后我们还需要关闭suggest,它提供搜索智能提示,在社工库中我们用不到这样的功能,重要的是,suggest会严重的拖慢solr的启动速度,在十几亿数据的情况下,开启suggest可能会导致solr启动加载core长达几个小时!
同样在solrconfig.xml中,找到这一段:
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str> <!-- org.apache.solr.spelling.suggest.fst -->
<str name="dictionaryImpl">DocumentDictionaryFactory</str><!-- org.apache.solr.spelling.suggest.HighFrequencyDictionaryFactory -->
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
</lst>
</searchComponent>
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy">
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
把这些全部删除,然后保存solrconfig.xml文件。
接下来把managed-schema拷贝一份,重命名为schema.xml (原文件不要删除),打开并找到以下位置:
只保留_version_和_root_节点,然后把所有的field,dynamicField和copyField全部删除,添加以下的部分:
<field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false" />
<field name="username" type="text_ik" indexed="true" stored="true"/>
<field name="email" type="text_ik" indexed="true" stored="true"/>
<field name="password" type="text_general" indexed="true" stored="true"/>
<field name="salt" type="text_general" indexed="true" stored="true"/>
<field name="ip" type="text_general" indexed="true" stored="true"/>
<field name="site" type="text_general" indexed="true" stored="true"/>
<field name="keyword" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="username" dest="keyword"/>
<copyField source="email" dest="keyword"/>
<uniqueKey>id</uniqueKey>
这里的uniqueKey是配置文件中原有的,用来指定索引字段,必须保留。新建了一个字段名为keyword,它的用途是联合查询,即当需要同时以多个字段做关键字查询时,可以用这一个字段名代替,增加查询效率,下面的copyField即用来指定复制哪些字段到keyword。注意keyword这样的字段,后面的multiValued属性必须为true。
username和email以及keyword这三个字段,用来检索查询关键字,它们的类型我们指定为text_ik,这是一个我们创造的类型,因为solr虽然内置中文分词,但效果并不好,我们需要添加IKAnalyzer中文分词引擎来查询中文。在https://github.com/EugenePig/ik-analyzer-solr5下载IKAnalyzer for solr5的源码包,然后使用Maven编译,得到一个文件IKAnalyzer-5.0.jar,把它放入solr-5.5.0/server/solr-webapp/webapp/WEB-INF/lib目录中,然后在solrconfig.xml的fieldType部分加入以下内容:
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index" useSmart="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
<analyzer type="query" useSmart="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
保存后,core的配置就算完成了,不过要导入mysql数据,我们还需要在mysql网站上下载mysql-connector-java-bin.jar库文件,连同solr-5.5.0/dist目录下面的solr-dataimporthandler-5.5.0.jar,solr-dataimporthandler-extras-5.5.0.jar两个文件,全部拷贝到solr-5.5.0/server/solr-webapp/webapp/WEB-INF/lib目录中,然后重启solr,就可以开始数据导入工作了。
误1、[MgmtSrvr] WARNING -- 1011 Unable to connect with connect string: nodeid=0,localhost:1186处理:一般这个情况是系统ping 127.0.0.1不通,可能是网卡问题,但是ping在eth0和eth1上配置的IP地址却通,所以处理方法是在/etc/hosts文件中添加:
192.168.1.5 localhost
即可。192.168.1.5根据自己配置的IP地址进行修改。
错误2、在修改了数据节点目录后,数据节点遇到如下错误:[ndbd] ERROR-- Couldn't start as daemon, error: 'Failed to lock pidfile '/opt/mysql_cluster/ndb_data/ndb_11.pid', errno: 37'
处理:由于数据节点的目录是挂载在nas存储上面,由于防火墙问题导致nas挂载异常,以致出现以上错误,关闭防火墙,重新挂载nas存储即可。
错误3、在修改了数据节点目录后,mysql节点遇到如下警告:[Warning] NDB : Tables not available after 15 seconds. Consider increasing --ndb-wait-setup value,导致管理节点识别不到mysql节点
处理:经检查,是配置文件my.cnf里ndb-connectstring参数的配置有误,改成正确的管理节点IP地址即可。
Warning: World-writable config file '/etc/my.cnf' is ignored
Unable to connect with connect string: nodeid=0,localhost:1186
Retrying every 5 seconds. Attempts left: 12 11 10 9 8 7 6 5 4 3 2 1, failed.
2011-06-08 23:31:35 [ndbd] ERROR-- Could not connect to management server, error: ''
解决办法 chmod 644 /etc/my.cnf
在solr与tomcat整合文章中,我用的索引库是mycore,现在就以这个为例。首先要准备jar包:solr-dataimporthandler-4.8.1.jar、solr-dataimporthandler-extras-4.8.1.jar和mysql-connector-java-5.0.7-bin.jar这三个包到solr的tomcat的webapps\solr\WEB-INF\lib下
在这个文件夹的conf下配置两个文件,添加一个文件。先配置solrconfig.xml。
在该文件下添加一个新节点。
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
在solrconfig.xml的同目录下创建data-config.xml。
配置:
复制代码
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/courseman"
user="root"
password="mysql" />
<document>
<entity name="student"
query="SELECT * FROM student">
<field column="id" name="id" />
<field column="name" name="name" />
<field column="gender" name="gender" />
<field column="major" name="major" />
<field column="grade" name="grade" />
</entity>
</document>
</dataConfig>
复制代码
schemal.xml的配置
复制代码
<?xml version="1.0" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License")you may not use this file except in compliance with
the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<schema name="example core one" version="1.1">
<fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<!-- general -->
<field name="id" type="int"indexed="true" stored="true" />
<field name="gender" type="string"indexed="true" stored="true" />
<field name="name" type="string"indexed="true" stored="true" />
<field name="major" type="string"indexed="true" stored="true" />
<field name="grade" type="string"indexed="true" stored="true" />
<field name="_version_" type="long" indexed="true" stored="true"/>
<!-- field to use to determine and enforce document uniqueness. -->
<uniqueKey>id</uniqueKey>
<!-- field for the QueryParser to use when an explicit fieldname is absent -->
<defaultSearchField>name</defaultSearchField>
<!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
<solrQueryParser defaultOperator="OR"/>
</schema>
复制代码
默认的文件不是这样的,稍微改动了一下。
field 的type类型是根据fieldtype 的name定义的。class是solr自定义的不能更改。
shcema.xml文件的field字段的属性介绍:
(1)name:字段名称
(2)type:字段类型(此处type不是java类型,而是下面定义的fieldType)
(3)indexed:是否索引看true--solr会对这个字段进行索引,只有经过索引的字段才能被搜索、排序等;false--不索引
(4)stored:是否存储看true--存储,当我们需要在页面显示此字段时,应设为true,否则false。
(5)required:是否必须看true--此字段为必需,如果此字段的内容为空,会报异常;false--不是必需
(6)multiValued:此字段是否可以保存多个值看
(7)omitNorms:是否对此字段进行解析看有时候我们想通过某个字段的完全匹配来查询信息,那么设置 indexed="true"、omitNorms="true"。
(8)default:设置默认值
有这样一个FieldType描述:
<fieldType name="text_general" positionIncrementGap="100">
<analyzer type="index">
<tokenizer/>
<filter ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter/>
</analyzer>
<analyzer type="query">
<tokenizer/>
<filter ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter/>
</analyzer>
</fieldType>
属性说明:
(1)name:类型名称,<field>中的type引用的就是这个name
(2)class:solr自定义的类型
(3)<analyzer type="index">定义建立索引时使用的分词器及过滤器
(4)<analyzer type="query">定义搜索时所使用的分词器及过滤器
(5)<tokenizer/>定义分词器
(6)<filter/>定义过滤器
uniqueKey属性
<uniqueKey>id</uniqueKey>
类似于数据表数据的id,solr索引库中最好定义一个用于标示document唯一性的字段,此字段主要用于删除document。
defaultSearchField属性
就是你在做query搜寻时若不指定特定栏位做检索时, Solr就会只查这个栏位.
<defaultSearchField>default</defaultSearchField>
copyField属性
是用来复制你一个栏位里的值到另一栏位用. 如你可以将name里的东西copy到major里, 这样solr做检索时也会检索到name里的东西.
<copyField source="name" dest="major"/>
现在可以将数据库的数据导入solr了。
点击Execute就可以了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)