悲观锁
一上来就给数据加锁,其他人不能操作。
全局锁,直接锁住整个索引
全局锁
PUT /fs/lock/global/_create
fs:你要上锁的index
lokc:上锁的type
global:对应的doc的id。
_create:强制必须时创建,如果文档已经存在,那么会创建失败,报错。
执行:
PUT /fs/lock/global/_create
{}
如果其他线程执行会报错:
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[lock][global]: version conflict, document already exists (current version [1])",
"index_uuid": "6bNW_JLFSN6UiboCRfKQ4A",
"shard": "2",
"index": "fs"
}
],
"type": "version_conflict_engine_exception",
"reason": "[lock][global]: version conflict, document already exists (current version [1])",
"index_uuid": "6bNW_JLFSN6UiboCRfKQ4A",
"shard": "2",
"index": "fs"
},
"status": 409
}
删除上的锁:
DELETE /fs/lock/global
第一个上锁成功的线程能执行修改操作。
操作简单,成本低,但是并发不高。。。
文档锁
创建索引及type
PUT /fs
PUT /fs/_mapping/lock
{
"lock":{
"properties":{
"process_id":{
"type":"long"
}
}
}
}
在es的config/scripts下创建judge-lock.groovy文件,
if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';
上文档锁
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 123
}
}
}
因为文档并不存在,会执行upsert中的语句,设置process_id的值为123,如果再次执行,因为process_id与文档中的值相同,则result值为noop。
如果传递不同的process_id,会报错。
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 222
}
}
}
刷新
POST /fs/_refresh
查询该线程锁了那些文档,
GET /fs/lock/_search?scroll=1m
{
"query": {
"term": {
"process_id": 123
}
}
}
然后批量删除
PUT /fs/lock/_bulk
{ "delete": { "_id": 1}}
然后其他的线程即可上锁了。
共享锁:这份数据是共享的,然后多个线程过来,都可以获取同一数据的共享锁,然后对这个数据执行读操作,
排他锁:只能有一个线程获取排他锁,然后执行增删改操作。
共享锁测试:
DELETE /fs
PUT /fs
PUT /fs/_mapping/lock
{
"lock":{
"properties":{
"lock_type":{
"type":"text"
},
"lock_count":{
"type":"long"
}
}
}
}
上共享锁:
POST /fs/lock/1/_update
{
"upsert": {
"lock_type": "shared",
"lock_count": 1
},
"script": {
"lang": "groovy",
"file": "judge-lock-2"
}
}
judge-lock-2文件内容:
judge-lock-2.groovy: if (ctx._source.lock_type == 'exclusive') { assert false }; ctx._source.lock_count++
多个线程都可获取,
排它锁
当有线程获取了共享锁,如果获取排它锁,会执行异常
PUT /fs/lock/1/_create
{ "lock_type": "exclusive" }
解除锁即删除文档即可。
DELETE /fs/lock/1