1瘩欺、對(duì)document level鎖,詳細(xì)的講解
全局鎖沫屡,一次性就鎖整個(gè)index饵隙,對(duì)這個(gè)index的所有增刪改操作都會(huì)被block住,如果上鎖不頻繁沮脖,還可以金矛,比較簡單
細(xì)粒度的一個(gè)鎖,document鎖勺届,顧名思義驶俊,每次就鎖你要操作的,你要執(zhí)行增刪改的那些doc免姿,doc鎖了饼酿,其他線程就不能對(duì)這些doc執(zhí)行增刪改操作了
但是你只是鎖了部分doc,其他線程對(duì)其他的doc還是可以上鎖和執(zhí)行增刪改操作的
document鎖胚膊,是用腳本進(jìn)行上鎖
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": "if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';"
"params": {
"process_id": 123
}
}
/fs/lock故俐,是固定的,就是說fs下的lock type紊婉,專門用于進(jìn)行上鎖
/fs/lock/id药版,比如1,id其實(shí)就是你要上鎖的那個(gè)doc的id喻犁,代表了某個(gè)doc數(shù)據(jù)對(duì)應(yīng)的lock(也是一個(gè)doc)
_update + upsert:執(zhí)行upsert操作
params槽片,里面有個(gè)process_id,process_id株汉,是你的要執(zhí)行增刪改操作的進(jìn)程的唯一id筐乳,比如說可以在java系統(tǒng)歌殃,啟動(dòng)的時(shí)候乔妈,給你的每個(gè)線程都用UUID自動(dòng)生成一個(gè)thread id,你的系統(tǒng)進(jìn)程啟動(dòng)的時(shí)候給整個(gè)進(jìn)程也分配一個(gè)UUID氓皱。process_id + thread_id就代表了某一個(gè)進(jìn)程下的某個(gè)線程的唯一標(biāo)識(shí)路召〔伲可以自己用UUID生成一個(gè)唯一ID
process_id很重要,會(huì)在lock中股淡,設(shè)置對(duì)對(duì)應(yīng)的doc加鎖的進(jìn)程的id身隐,這樣其他進(jìn)程過來的時(shí)候,才知道唯灵,這條數(shù)據(jù)已經(jīng)被別人給鎖了
assert false贾铝,不是當(dāng)前進(jìn)程加鎖的話,則拋出異常
ctx.op='noop'埠帕,不做任何修改
如果該document之前沒有被鎖垢揩,/fs/lock/1之前不存在,也就是doc id=1沒有被別人上過鎖; upsert的語法敛瓷,那么執(zhí)行index操作叁巨,創(chuàng)建一個(gè)/fs/lock/id這條數(shù)據(jù),而且用params中的數(shù)據(jù)作為這個(gè)lock的數(shù)據(jù)呐籽。process_id被設(shè)置為123锋勺,script不執(zhí)行。這個(gè)時(shí)候象征著process_id=123的進(jìn)程已經(jīng)鎖了一個(gè)doc了狡蝶。
如果document被鎖了庶橱,就是說/fs/lock/1已經(jīng)存在了,代表doc id=1已經(jīng)被某個(gè)進(jìn)程給鎖了牢酵。那么執(zhí)行update操作悬包,script,此時(shí)會(huì)比對(duì)process_id馍乙,如果相同布近,就是說,某個(gè)進(jìn)程丝格,之前鎖了這個(gè)doc撑瞧,然后這次又過來,就可以直接對(duì)這個(gè)doc執(zhí)行操作显蝌,說明是該進(jìn)程之前鎖的doc预伺,則不報(bào)錯(cuò),不執(zhí)行任何操作曼尊,返回success; 如果process_id比對(duì)不上酬诀,說明doc被其他doc給鎖了,此時(shí)報(bào)錯(cuò)
/fs/lock/1
{
"process_id": 123
}
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": "if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';"
"params": {
"process_id": 123
}
}
script:ctx._source.process_id骆撇,123
process_id:加鎖的upsert請(qǐng)求中帶過來額proess_id
如果兩個(gè)process_id相同瞒御,說明是一個(gè)進(jìn)程先加鎖,然后又過來嘗試加鎖神郊,可能是要執(zhí)行另外一個(gè)操作肴裙,此時(shí)就不會(huì)block趾唱,對(duì)同一個(gè)process_id是不會(huì)block,ctx.op= 'noop'蜻懦,什么都不做甜癞,返回一個(gè)success
如果說已經(jīng)有一個(gè)進(jìn)程加了鎖了
/fs/lock/1
{
"process_id": 123
}
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": "if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';"
"params": {
"process_id": 234
}
}
"script": "if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';"
ctx._source.process_id:123
process_id: 234
process_id不相等,說明這個(gè)doc之前已經(jīng)被別人上鎖了宛乃,process_id=123上鎖了; process_id=234過來再次嘗試上鎖悠咱,失敗,assert false征炼,就會(huì)報(bào)錯(cuò)
此時(shí)遇到報(bào)錯(cuò)的process乔煞,就應(yīng)該嘗試重新上鎖,直到上鎖成功
有報(bào)錯(cuò)的話柒室,如果有些doc被鎖了渡贾,那么需要重試
直到所有鎖定都成功,執(zhí)行自己的操作雄右。空骚。。
釋放所有的鎖
2擂仍、上document鎖的完整實(shí)驗(yàn)過程
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
}
}
}
{
"_index": "fs",
"_type": "lock",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
GET /fs/lock/1
{
"_index": "fs",
"_type": "lock",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"process_id": 123
}
}
POST /fs/lock/1/_update
{
"upsert": { "process_id": 234 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 234
}
}
}
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[4onsTYV][127.0.0.1:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "error evaluating judge-lock",
"caused_by": {
"type": "power_assertion_error",
"reason": "assert false\n"
},
"script_stack": [],
"script": "",
"lang": "groovy"
}
},
"status": 400
}
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 123
}
}
}
{
"_index": "fs",
"_type": "lock",
"_id": "1",
"_version": 1,
"result": "noop",
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
}
}
POST /fs/file/1/_update
{
"doc": {
"name": "README1.txt"
}
}
{
"_index": "fs",
"_type": "file",
"_id": "1",
"_version": 4,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
POST /fs/_refresh
GET /fs/lock/_search?scroll=1m
{
"query": {
"term": {
"process_id": 123
}
}
}
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAACPkFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAj5RY0b25zVFlWWlRqR3ZJajlfc3BXejJ3AAAAAAAAI-YWNG9uc1RZVlpUakd2SWo5X3NwV3oydwAAAAAAACPnFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAj6BY0b25zVFlWWlRqR3ZJajlfc3BXejJ3",
"took": 51,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "fs",
"_type": "lock",
"_id": "1",
"_score": 1,
"_source": {
"process_id": 123
}
}
]
}
}
PUT /fs/lock/_bulk
{ "delete": { "_id": 1}}
{
"took": 20,
"errors": false,
"items": [
{
"delete": {
"found": true,
"_index": "fs",
"_type": "lock",
"_id": "1",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 200
}
}
]
}
POST /fs/lock/1/_update
{
"upsert": { "process_id": 234 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 234
}
}
}
process_id=234上鎖就成功了