需求:对类似文件系统这种的有多层级关系的数据进行建模;
1、文件系统数据构造
PUT /filesystem
{
"settings": {
"analysis": {
"analyzer": {
"paths": {
"tokenizer": "path_hierarchy"
}
}
}
}
}
其中path_hierarchy tokenizer,对应将路径
/a/b/c/d --> path_hierarchy -> /a/b/c/d, /a/b/c, /a/b, /a
2、设置mapping
PUT /filesystem/_mapping/file
{
"properties": {
"name": {
"type": "keyword"
},
"path": {
"type": "keyword",
"fields": {
"tree": {
"type": "text",
"analyzer": "paths"
}
}
}
}
}
3、添加数据
PUT /filesystem/file/1
{
"name": "README.txt",
"path": "/workspace/projects/helloworld",
"contents": "这是我的第一个elasticsearch程序"
}
4、对文件系统执行搜索
需求1:查找一份,内容包括elasticsearch,在/workspace/projects/hellworld这个目录下的文件
GET /fs/file/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"contents": "elasticsearch"
}
},
{
"constant_score": {
"filter": {
"term": {
"path": "/workspace/projects/helloworld"
}
}
}
}
]
}
}
}
需求2:搜索/workspace目录下,内容包含elasticsearch的所有的文件
GET /fs/file/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"contents": "elasticsearch"
}
},
{
"constant_score": {
"filter": {
"term": {
"path.tree": "/workspace"
}
}
}
}
]
}
}
}
5、悲观锁并发控制
乐观锁的概念:首先获取对应数据的版本号,带着当前获取的version去执行修改,如果一旦发现当前version跟之前自己获取的不一样,则必须重新获取新的version号再次尝试修改;
悲观锁的概念:直接给数据加锁,此时就只有你能执行各种各样的操作,其他人不能执行操作;
(1)基于es全局锁实现
PUT /filesystem/lock/global/_create
{}
filesystem: 你要上锁的那个index
lock: 指定的一个对这个index上全局锁的一个type
global: 上的全局锁对应的这个doc的id
_create:强制必须是创建,如果/filesystem/lock/global这个doc已经存在,那么创建失败,报错
此时另外一个线程尝试加锁
PUT /filesystem/lock/global/_create
{}
加锁报错。。。
当前线程可以执行各种操作
POST /filesystem/file/1/_update
{
"doc": {
"name": "README1.txt"
}
}
然后释放锁
DELETE /fs/lock/global
(2)全局锁的优点和缺点
优点:操作非常简单,非常容易使用,成本低
缺点:对整个index加锁,对index中所有的doc的操作都会被block住,导致整个系统的并发能力很低。
6、基于document实现乐观锁
document锁,执行增删改的那些doc锁,其他线程就不能对这些doc执行增删改操作了,但是你只是锁了部分doc,其他线程对其他的doc还是可以上锁和执行增删改操作;
document锁使用脚本加锁
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,专门用于进行上锁
/fs/lock/id,比如1,id其实就是你要上锁的那个doc的id,代表了某个doc数据对应的lock(也是一个doc)
_update + upsert:执行upsert操作
params,里面有个process_id,process_id,是你的要执行增删改操作的进程的唯一id,比如说可以在java系统,启动的时候,给你的每个线程都用UUID自动生成一个thread id,你的系统进程启动的时候给整个进程也分配一个UUID。process_id + thread_id就代表了某一个进程下的某个线程的唯一标识。可以自己用UUID生成一个唯一ID;
加锁的过程:
(1)、在scripts/文件夹下创建judge-lock.groovy脚本,内容为
if ( ctx._source.process_id != process_id ) { assert false }; ctx.op = 'noop';
(2)、es加锁
POST /fs/lock/1/_update
{
"upsert": { "process_id": 123 },
"script": {
"lang": "groovy",
"file": "judge-lock",
"params": {
"process_id": 123
}
}
}
(3)、获取锁的情况
GET /fs/lock/1
{
"_index": "fs",
"_type": "lock",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"process_id": 123
}
}
(4)、另一个线程加锁,加锁失败
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
}
(5)、相同的线程加锁会成功
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
}
}
(6)、获取对应线程对哪些文档加了锁
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
}
}
]
}
}
(7)、释放锁
PUT /fs/lock/_bulk
{ "delete": { "_id": 1}}