全文检索引擎Solr系列——solr入门
普通关系型数据库使用的是(悲观并发控制(PCC))
当我们在修改一个数据前先锁定这一行,然后确保只有读取到数据的这个线程可以修改这一行数据
ES使用的是(乐观并发控制(OCC))
ES不会阻止某一数据的访问,然而,如果基础数据在我们读取和写入的间隔中发生了变化,更新就会失败,这时候就由程序来决定如何处理这个冲突。它可以重新读取新数据来进行更新,又或者将这一情况直接反馈给用户。
本文中的示例是在ES7.1.1上执行的。
ES如何实现版本控制(使用es内部版本号)
1)首先得到想要修改的文档,获取版本version号
先为duan的索引增加一条数据,我执行了2次:
PUT /duan/_doc/1
{
"member_id":"abc",
"amount":302,
"event_time":"2020-05-03 10:07:01"
}
返回:
{
"_index" : "duan",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
或者直接查询一下:
GET /duan/_doc/1
{
"_index" : "duan",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"member_id" : "abc",
"amount" : 302,
"event_time" : "2020-05-03 10:07:01"
}
}
返回中的_version就是ES为我们准备的内部version了。
使用内置_version实战乐观锁控制效果
当前的version是2,我们使用一个浏览器标签页,发出更新请求,把当前的version带上:
POST /duan/_doc/1?version=2
{
"member_id":"abc",
"amount":303,
"event_time":"2020-05-03 10:07:01"
}
返回:
{
"error": {
"root_cause": [
{
"type": "action_request_validation_exception",
"reason": "Validation Failed: 1: internal versioning can not be used for optimistic concurrency control. Please use `if_seq_no` and `if_primary_term` instead;"
}
],
"type": "action_request_validation_exception",
"reason": "Validation Failed: 1: internal versioning can not be used for optimistic concurrency control. Please use `if_seq_no` and `if_primary_term` instead;"
},
"status": 400
}
百度了下,是ES版本支持的问题
这时我们在操作es的时候可以通过_seq_no这个es自带的字段进行控制
注意:一些老的版本es使用version,但是新版本不支持了,会报这个错误,提示我们用if_seq_no和if_primary_term
版本元数据
_seq_no:文档版本号,作用同_version(相当于学生编号,每个班级的班主任为学生分配编号,效率要比学校教务处分配来的更加高效,管理起来更方便)
_primary_term:文档所在位置(相当于班级)
官文地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/optimistic-concurrency-control.html
正确的做法如下:
POST /duan/_doc/1/_update?if_seq_no=2&if_primary_term=1
{
"doc":{
"amount":333
}
}
返回:
#! Deprecation: [types removal] Specifying types in document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.
{
"_index" : "duan",
"_type" : "mytype",
"_id" : "1",
"_version" : 3,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
相同的if_seq_no=2&if_primary_term=1再执行一次,失败的结果如下:
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[1]: version conflict, required seqNo [1], primary term [1]. current document has seqNo [2] and primary term [1]",
"index_uuid": "TsS_bkFJRE6wdpOSzIrcEw",
"shard": "0",
"index": "duan"
}
],
"type": "version_conflict_engine_exception",
"reason": "[1]: version conflict, required seqNo [1], primary term [1]. current document has seqNo [2] and primary term [1]",
"index_uuid": "TsS_bkFJRE6wdpOSzIrcEw",
"shard": "0",
"index": "duan"
},
"status": 409
}
关键错误信息:version_conflict_engine_exception,版本冲突,将if_seq_no升到3,模拟失败后重试,此时更新成功。
真实的场景,重试的次数跟线程并发数有关,线程越多,更新越频繁,就可能需要重试多次才可能更新成功。
使用外部_version实战乐观锁控制效果
ES允许不使用内置的version进行版本控制,可以自定义使用外部的version,例如常见的使用Elasticsearch做数据查询加速的经典方案,关系型数据库作为主数据库,然后使用Elasticsearch做搜索数据,主数据会同步数据到Elasticsearch中,而主数据库并发控制,本身就是使用的乐观锁机制,有自己的一套version生成机制,数据同步到ES那里时,直接使用更方便。
请求语法上加上version_type参数即可:
POST /duan/_doc/1?version=2&version_type=external
{
"doc":{
"amount":999
}
}
返回:
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[1]: version conflict, current version [3] is higher or equal to the one provided [2]",
"index_uuid": "TsS_bkFJRE6wdpOSzIrcEw",
"shard": "0",
"index": "duan"
}
],
"type": "version_conflict_engine_exception",
"reason": "[1]: version conflict, current version [3] is higher or equal to the one provided [2]",
"index_uuid": "TsS_bkFJRE6wdpOSzIrcEw",
"shard": "0",
"index": "duan"
},
"status": 409
}
调整下version=3,再执行一次
{
"_index" : "duan",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
唯一的区别
- 内置_version,只有当你提供的version与es中的_version完全一样的时候,才可以进行更新,否则报错;
- 外部_version,只有当你提供的version比es中的_version大的时候,才能完成修改。
Replica Shard数据同步并发控制
在Elasticsearch内部,每当primary shard收到新的数据时,都需要向replica shard进行数据同步,这种同步请求特别多,并且是异步的。如果同一个document进行了多次修改,Shard同步的请求是无序的,可能会出现"后发先至"的情况,如果没有任何的并发控制机制,那结果将无法相像。
Shard的数据同步也是基于内置的_version进行乐观锁并发控制的。
例如Java客户端向Elasticsearch某条document发起更新请求,共发出3次,Java端有严谨的并发请求控制,在ElasticSearch的primary shard中写入的结果是正确的,但Elasticsearch内部数据启动同步时,顺序不能保证都是先到先得,情况可能是这样,第三次更新请求比第二次更新请求先到,如下图:
如果Elasticsearch内部没有并发的控制,这个document在replica的结果可能是text2,并且与primary shard的值不一致,这样肯定错了。
预期的更新顺序应该是text1-->text2-->text3,最终的正确结果是text3。那Elasticsearch内部是如何做的呢?
Elasticsearch内部在更新document时,会比较一下version,如果请求的version与document的version相等,就做更新,如果document的version已经大于请求的version,说明此数据已经被后到的线程更新过了,此时会丢弃当前的请求,最终的结果为text3。
此时的更新顺序为text1-->text3,最终结果也是对的。
原文链接:https://blog.csdn.net/kuangxie4668/java/article/details/105547435
参考:https://www.cnblogs.com/huangying2124/archive/2019/12/05/11986897.html
全文检索引擎Solr系列——solr入门的更多相关文章
- 全文检索引擎Solr系列——Solr核心概念、配置文件
Document Document是Solr索引(动词,indexing)和搜索的最基本单元,它类似于关系数据库表中的一条记录,可以包含一个或多个字段(Field),每个字段包含一个name和文本值. ...
- 搜索引擎solr系列---solr分词配置
分词我理解的是,输入的一句话,按照它自己定义的规则分为常用词语. 首先,Solr有自己基本的类型,string.int.date.long等等. 对于string类型,比如在你的core/conf ...
- [摘]全文检索引擎Solr系列—–全文检索基本原理
原文链接--http://www.importnew.com/12707.html 全文检索引擎Solr系列—–全文检索基本原理 2014/08/18 | 分类: 基础技术, 教程 | 2 条评论 | ...
- 全文检索引擎 Solr 部署与基本原理
全文检索引擎 Solr 部署与基本原理 搜索引擎Solr环境搭建实例 关于 solr , schema.xml 的配置说明 全文检索引擎Solr系列-–全文检索基本原理 一.搜索引擎Solr环境搭建实 ...
- 全文检索引擎Solr 指南
全文检索引擎Solr系列:第一篇:http://t.cn/RP004gl.第二篇:http://t.cn/RPHDjk7 .第三篇:http://t.cn/RPuJt3T
- 全文检索引擎及工具 Lucene Solr
全文检索引擎及工具 lucence lucence是一个全文检索引擎. lucence代码级别的使用步骤大致如下: 创建文档(org.apache.lucene.document.Document), ...
- Solr全文检索引擎配置及使用方法
介绍 Solr是一款开源的全文检索引擎,基于lucene.拥有完善的可配置功能界面.具有丰富的查询语言,可扩展,可优化. 下载安装 进入solr官网下载包(这里我使用的版本是8.0) http://w ...
- 全文检索选择-------- Elasticsearch与Solr
Elasticsearch简介* Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据. 它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三 ...
- solr课程学习系列-solr服务器配置(2)
本文是solr课程学习系列的第2个课程,对solr基础知识不是很了解的请查看solr课程学习系列-solr的概念与结构(1) 本文以windows的solr6服务器搭建为例. 一.solr的工作环境: ...
随机推荐
- Syscall param open(filename) points to unaddressable byte(s)
valgrind 调试出现如题所示的错误,原因是存取文件名的空间被释放了 源代码: cfg->snteam_cfg->snt.score.nd.wrd_dict_db_fn=cfg-> ...
- rac 11g_生产库日志组损坏处理
原创作品,出自 "深蓝的blog" 博客,转载时请务必注明出处,否则有权追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong/ar ...
- Unix 入门
说明:转自以为大神的笔记. 首先,我们一起看看UNIX的目录,因为清楚了目录,才能对UNIX的框架有个大概的印象!当然这里讲的是系统正常运转所必须的,并且一定不能删除或者修改. / 是系统的根目录: ...
- Maximum number of WAL files in the pg_xlog directory (2)
Jeff Janes: Hi, As part of our monitoring work for our customers, we stumbled upon an issue with our ...
- Discuz 3.X 整合 CAS 的方法
1,新建 CasClient.php <?php include_once (dirname ( __FILE__ ) . '/CasClientConfig.php'); // 注意这个 in ...
- 【转】第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析
作者: 牛A与牛C之间 时间: 2013-11-21 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第6篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- js 监听整个页面的回车事件
JS监听整个页面的回车事件 <script type="text/javascript"> document.onkeydown=keyDownSearch; ...
- R提高篇(四): 数据管理二
目录: 数学函数 统计函数 应用示例 控制流 数学函数 ceiling(x): 大于等于 x 的最小整数, 如: ceiling(3.213) --> 4 floor(x): 小 ...
- POJ #1015 - Jury Compromise - TODO: POJ website issue
(poj.org issue. Not submitted yet) This is a 2D DP problem, very classic too. Since I'm just learnin ...
- 【Log4j】 log4j.properties 使用
一.参数意义说明 输出级别的种类 ERROR.WARN.INFO.DEBUG ERROR 为严重错误 主要是程序的错误 WARN 为一般警告,比如session丢失 INFO 为一般要显示的信息,比如 ...