概述
1. UUID
首先了解一下什么是UUID,参考百度百科UUID
UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写;
UUID是基于当前时间、计数器(counter)和硬件标识(通常为无线网卡的MAC地址)等数据计算生成的;
UUID全局(分布式系统上)唯一
有不同的生成算法和生成长度,应用于数据库的主键的时候不用考虑重复的问题。
UUID的好处和坏处,参考:为什么MySQL不推荐使用uuid作为主键?和MySQL不建议用UUID做innodb主键的几条原因
- UUID虽然能够保证ID的唯一性,但是无法满足业务系统需要的很多其他特性,例如:时间粗略有序性、可反解和可制造性;
- UUID产生时使用完全的时间数据,性能比较差;
- UUID比较长,会占用空间大,间接导致数据库性能下降;
- UID并不具有有序性,会导致B+树索引在写的时候有过多的随机写操作(连续的ID会产生部分顺序写);
- 在写的时候不能产生有序的append操作,而需要进行insert操作,将读取整个B+树节点到内存,在插入这条记录后会将整个节点写回磁盘,这种操作在记录占用空间比较大的情况下,性能会明显下降。
- UUID目前不是顺序增长,做为主键写入导致,随机IO严重。
2. anyq的solr中配置文件和逻辑
solr中配置uuid,参考: Solr自动生成ID
虽然这个uuid性能看起来似乎不太好,但是我的数据集比较小,所以暂时不需要太担心这个问题。
0. 失败风险
- 有可能因为配置id时,没有注释之前的id,而又重新弄了一个类型为uuid的id,就会冲突。
- 配置时使用了uuid,但是另外有其他程序加入数据时使用了id,也会冲突
由于anyq,添加数据的时候,就包括了对id的处理;同时,其schema.xml文件也是在数据处理过程中覆盖生成的,所以单纯修改配置文件,无法达到效果。这里选择放弃。
2.1 配置文件位置和内容
①配置文件solrconfig.xml
- 所在位置:
/home/AnyQ-master/build/solr-4.10.3-anyq/example/solr/mask_core/conf/solrconfig.xml
- 这个文件中没有出现
id
、answer
和question
的模式定义 - 出现了
updateRequestProcessorChain
,如下:<requestHandler name="/update" class="solr.UpdateRequestHandler"> <!-- See below for information on defining updateRequestProcessorChains that can be used by name on each Update Request --> <!-- <lst name="defaults"> <str name="update.chain">dedupe</str> </lst> --> </requestHandler>
②配置文件managed-schema.xml
,
- 所在位置:
/home/AnyQ-master/build/solr-4.10.3-anyq/example/solr/mask_core/conf/managed-schema.xml
- 内容中包含id的部分(这个文件中没有搜索到
question
和answer
):<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
③配置文件schema.xml.bak
- 所在位置:
/home/AnyQ-master/build/solr-4.10.3-anyq/example/solr/mask_core/conf
- 内容中也是只包含
id
,没有包含answer
和question
,基本和上面的差不多。<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
- 关于
schema.xml
和managed-schema.xml
文件,参考:solr 学习笔记2-----schema和field typeschema文件详细存储了field和field type信息。初始化配置的不同,或是后面配置的修改会导致所使用的shema文件不同。
managed-schema.xml文件,是默认的schema配置文件。只能通过schema api 修改。
schema.xml文件,只能手动修改.
两个文件的内容是一样的,只是修改文件的方式不同 - 另外,参考:认识配置文件schema.xml(managed-schema)可知:
- 采用哪个配置是根据
solrconfig.xml
中以下字段决定的,搜索schemaFactory
,托管模式,未备注释。
<schemaFactory class="ManagedIndexSchemaFactory"> <bool name="mutable">true</bool> <str name="managedSchemaResourceName">managed-schema.xml</str> </schemaFactory>
- 经典模型,被注释了
<!-- <schemaFactory class="ClassicIndexSchemaFactory"/> -->
- 所以anyq的这个solr用的是托管模式的
managed-schema.xml
文件。
- 采用哪个配置是根据
④生成的faq对应的配置文件schema_format
,
- 所在位置:
/home/AnyQ-master/build/faq/schema_format
, - 内容(和
managed-schema.xml
中内容比较匹配。):[ { "indexed": true, "stored": true, "type": "text_multi_lang", "name": "question" }, { "indexed": false, "stored": true, "type": "string", "name": "answer" } ]
参考:
- 配置Solr UUID时出现的异常
- Solr4.0 如何配置使用UUID自动生成id值
- Solr 设置UUID自动生成
- Configuring Solr to use UUID as a key
2.2 配置文件生效逻辑
在上一部分可以知道,使用的配置文件其实是managed-schema.xml
文件,需要向该配置文件添加修改的内容来自schema_format
。
其中,比较重要的实现逻辑的功能脚本位于:/home/AnyQ-master/build/solr_script
:
[root@567b3aed2b1c solr_script]# tree -L 1
.
├── anyq_solr.sh # 整体逻辑控制
├── make_json.py # 把faq内容转为kson格式
├── sample_docs # faq源文本
├── solr_api.py # solr的api,其实还是调用了solr_tools.py
├── solr_deply.sh # 主要包括启动和停止solr服务这两个功能实现 (solr_server项的值)
├── solr_tools.py # utils功能函数
└── solr_tools.pyc
大概画了一个逻辑流程图
其中和配置项目相关的就是第6步骤,
url = "http://{}:{}/solr/{}/schema/fields".format(host, port, enginename)
访问自己对应的solr网址,可以去看看这个接口的内容,类似下面
其中就包括,id
、answer
、question
这三个内容。虽然查看对应的mask_core/conf/managed_schema.xml
文件中依然没有这三个field。
完整的代码是:
def set_engine_schema(host, enginename, schema_config, port=8983):
"""
Set the data format for engine
schema_config can be a json path or a dict
"""
#读取schema_format文件内容,格式化成json
if isinstance(schema_config, str):
if not os.path.isfile(schema_config):
print _make_smart_hint(HINT_TYPE_NOR_ERR, "Wrong config file path")
return
with open(schema_config) as f:
schema_config = encode_utf8(json.load(f))
print schema_config
assert isinstance(schema_config, list), "schema_config is required to be a list object"
# request URL
# 发送请求url
url = "http://{}:{}/solr/{}/schema/fields".format(host, port, enginename)
try:
req = urllib2.Request(url)
req.headers = HEADER
response = urllib2.urlopen(req, json.dumps(schema_config, ensure_ascii=False))
# urlopen方法,其实就是post方法,所以这里就将schema_format数据转成的schema_config数据通过schema接口传到了managed_schema.xml
print response.read()
except urllib2.HTTPError as err:
_get_error_message(err.read())
2.3 solr的schema API
参考:
- ✅ Solr系列三:solr索引详解(Schema介绍、字段定义详解、Schema API 介绍) 中三、Schema API介绍部分
- Solr的Schema API(模式)
- Apache Document——Schema API
Schema API是一套REST风格的API,用户可以通过浏览器,或者使用某种语言中的HTTPClient
对象进行访问。
但是调研了一波发现,似乎没法直接通过schema的API设置好UUID
2.4 设置UUID
2.4.1 基本设置
- 缕清了anyq中关于solr的配置,其实直接按照这个人的设置一下,就差不多了。anyq中其实没有对id做额外规定。
- Solr 设置UUID自动生成
先备份旧的,复制一份,改。。免得出错,都改不回来。。????
修改managed-schema.xml文件
cd /mask_core/conf
cp managed-schema.xml managed-schema-old.xml
vi managed-schema.xml
# 命令行模式下,:/id 搜索id,回车就会定位到一个要搜索的内容
# n 下一个
# N (shift+n) 上一个
# 找到id对应的filed
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
# 改为
<field name="id" type="uuid" indexed="true" stored="true" multiValued="false" />
# 在field中只用把type改为uuid即可
# 添加uuid字段类型(我直接加在xml文件最开始fieldType开始的地方)
<fieldType name="uuid" class="solr.UUIDField" indexed="true" />
修改solrconfig.xml文件
cp solrconfig.xml solrconfig_old.xml
vi solrconfig.xml
# 添加自动生成UUID的updateRequestProcessorChain
# 添加更新策略配置,调用Solr中的UUIDUpdateProcessorFactory生成全局唯一的UUID
<updateRequestProcessorChain name="uuid">
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.DistributedUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
<updateRequestProcessorChain name="uuid">
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>
# 上面这两种随便选一种,我选的第二种,看起来更简单一点。
# 这里需要注意,有不同类型的requestHandler
# requestHandler的name包括:
<requestHandler name="/select" class="solr.SearchHandler">
<requestHandler name="/query" class="solr.SearchHandler">
<requestHandler name="/get" class="solr.RealTimeGetHandler">
<requestHandler name="/export" class="solr.SearchHandler">
<requestHandler name="/update" class="solr.UpdateRequestHandler">
# 这里其实只更新updata的这个requestHandler就好了(这样每次更新数据的时候,就会触发这个handler,自动生成uuid),因为我应该用不到dataimport-handler,如果用到的话,就需要都定义一下
# update这部分修改之前的样子
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<!-- See below for information on defining
updateRequestProcessorChains that can be used by name
on each Update Request
-->
<!--
<lst name="defaults">
<str name="update.chain">dedupe</str>
</lst>
-->
</requestHandler>
# 其实把注释删掉,把str改了就好了,如下
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<lst name="defaults">
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
# 如果需要改dataimport的话,如下,但是我没有试验过。。
<requestHandler name="/dataimport" class="solr.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
改好了之后,需要重启solr。这里使用的是mask_core,所以需要修改对应的脚本文件
cd /home/AnyQ-master/build/
# 关了之后再启动,就是重启
sh solr_script/solr_deply.sh stop ./solr-4.10.3-anyq 8900
# sh solr_deply.sh stop solr_home solr_port
# 再启动
sh solr_script/solr_deply.sh start ./solr-4.10.3-anyq 8900
# 不报错的话,加点数据进去看看
sh solr_script/anyq_solr_mask.sh solr_script/mask_docs
加数据的时候,报错
需要把上传数据部分中,有关id
的部分删掉,不能上传id了。修改make_json.py
脚本,主要是run
函数,注释掉其中和id相关的部分即可。如下:
faq_file = open(faq_file_str, "r")
for line in faq_file:
arr = line.strip().split('t')
if header == 0:
header = 1
field_names = arr
field_cnt = len(field_names)
if 'question' not in field_names or 'answer' not in field_names:
print >> sys.stderr, "need question and answer"
sys.exit(6)
#if 'id' not in field_names:
#auto_id = True
write_format_file(field_names, format_file_str)
json_file = open(json_file_str, "w")
continue
if len(arr) != field_cnt:
print >> sys.stderr, "line error"
continue
#idx += 1
data = dict([field_names[i], arr[i]] for i in range(field_cnt))
#if auto_id:
#data['id'] = str(idx)
json_file.write(json.dumps(data, ensure_ascii=False))
json_file.write("n")
json_file.close()
faq_file.close()
再去上传数据,看结果。已经OK了
确实都是随机生成的奇怪的id。
2.4.2 效果验证
Field-Type已经从StrField
变成了
UUIDField
类型
直接通过Document
界面添加一条数据,例如:{"question":"计算机学科包括哪些主要课程?","answer":"计算机组成原理,数据结构,算法实现"}
。
然后去query的时候,就可以看到,这个id,其实已经配好了
再去看看整体的数据,其实也已经加好了,从100条口罩数据,加了一条计算机数据。OK
其他 错误解决
注意,启动时报错了,截图如下:
感谢:【Solr】Solr配置更新索引时使用UUID (以下为复制内容)
参考:Using solr.UUIDField give -> Caused by: org.apache.solr.common.SolrException: Invalid UUID String: ‘1’
It appears based on the bug report that you have modified the example solr schema.xml to change the uniqueKey field to use UUIDField - however you also seem to still have the QueryElevationComponent enabled in your solrconfig.xml file, configured to use the uniqueKey field, and the elevate.xml file has (example) entries referring to IDs which are not legal UUID values.
So you can either remove the QueryElevationComponent, or edit elevate.xml to remove the examples from elevate.xml, or change the QueryElevationComponent configuration in solrconfig.xml to use some lookup field other then the uniqueKey field.
由于之前直接复制example里的配置文件进行配置,在solrconfig.xml
配置的searchComponent
使用了elevate.xml
与solrconfig.xml
文件同级的文件夹,可以看到有一个文件elevate.xml
,内容如下:
把其中<doc>
部分的内容注释掉就好了,类似这样就行
(注意,<!-- -->
注释符号里面不能再有注释,不然会报错),最开始写的是
<!--
<doc id="MA147LL/A" /> <!-- deffveverver -->
<doc id="IW-02" exclude="true" />
-->
然后就报错了。。。Caused by: org.apache.solr.common.SolrException: org.xml.sax.SAXParseException; systemId: solrres:/elevate.xml; lineNumber: 35; columnNumber: 32; The string "--" is not permitted within comments.
然后再次重启。
参考:
- python用post方法,向solr进行删除,更新,插入操作
- python对solr进行查询、插入操作(GETPOST)
- 使用python操作solr
- Solr7.4.0的API(Solrj)操作
- Solr API for Python
最后
以上就是还单身白羊为你收集整理的百度AnyQ之九——设置UUID1. UUID2. anyq的solr中配置文件和逻辑的全部内容,希望文章能够帮你解决百度AnyQ之九——设置UUID1. UUID2. anyq的solr中配置文件和逻辑所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复