blob: fe15e3e63a869c83401bcd94521a526078438f31 [file] [log] [blame]
<!doctype html><html lang=cn class=no-js><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=generator content="Hugo 0.102.3"><link rel=canonical type=text/html href=/cn/docs/guides/><link rel=alternate type=application/rss+xml href=/cn/docs/guides/index.xml><meta name=robots content="noindex, nofollow"><link rel="shortcut icon" href=/favicons/favicon.ico><link rel=apple-touch-icon href=/favicons/apple-touch-icon-180x180.png sizes=180x180><link rel=icon type=image/png href=/favicons/favicon-16x16.png sizes=16x16><link rel=icon type=image/png href=/favicons/favicon-32x32.png sizes=32x32><link rel=icon type=image/png href=/favicons/android-36x36.png sizes=36x36><link rel=icon type=image/png href=/favicons/android-48x48.png sizes=48x48><link rel=icon type=image/png href=/favicons/android-72x72.png sizes=72x72><link rel=icon type=image/png href=/favicons/android-96x96.png sizes=96x96><link rel=icon type=image/png href=/favicons/android-144x144.png sizes=144x144><link rel=icon type=image/png href=/favicons/android-192x192.png sizes=192x192><title>GUIDES | HugeGraph</title><meta name=description content><meta property="og:title" content="GUIDES"><meta property="og:description" content="Apache HugeGraph 官网"><meta property="og:type" content="website"><meta property="og:url" content="/cn/docs/guides/"><meta property="og:site_name" content="HugeGraph"><meta itemprop=name content="GUIDES"><meta itemprop=description content="Apache HugeGraph 官网"><meta name=twitter:card content="summary"><meta name=twitter:title content="GUIDES"><meta name=twitter:description content="Apache HugeGraph 官网"><link rel=preload href=/scss/main.min.14ea575cb35d93d46ff8681b2334f40fd46243c100c5c39f5a841b931fae2d40.css as=style><link href=/scss/main.min.14ea575cb35d93d46ff8681b2334f40fd46243c100c5c39f5a841b931fae2d40.css rel=stylesheet integrity><script src=https://code.jquery.com/jquery-3.5.1.min.js integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin=anonymous></script>
<link rel=stylesheet href=/css/prism.css><script type=application/javascript>var doNotTrack=!1;doNotTrack||(window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)},ga.l=+new Date,ga("create","UA-00000000-0","auto"),ga("send","pageview"))</script><script async src=https://www.google-analytics.com/analytics.js></script></head><body class=td-section><header><nav class="js-navbar-scroll navbar navbar-expand navbar-dark flex-column flex-md-row td-navbar"><a class=navbar-brand href=/cn/><span class=navbar-logo><svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1{fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:.5px;opacity:.3}.cls-2{fill:#229efa}.cls-3{fill:#9948f7}.cls-4{fill:#33bc7a}.cls-5{fill:url(#未命名的渐变_3)}.cls-6{fill:url(#未命名的渐变_13)}.cls-7{fill:url(#未命名的渐变_11)}</style><linearGradient id="未命名的渐变_3" x1="6.16" y1="14.63" x2="6.16" y2="6.01" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2e3192"/><stop offset="0" stop-color="#229efa"/><stop offset=".44" stop-color="#239cf8"/><stop offset=".6" stop-color="#2795f2"/><stop offset=".71" stop-color="#2d8ae8"/><stop offset=".81" stop-color="#3679d9"/><stop offset=".89" stop-color="#4263c6"/><stop offset=".95" stop-color="#5048af"/><stop offset="1" stop-color="#5c319b"/></linearGradient><linearGradient id="未命名的渐变_13" x1="10.75" y1="8.2" x2="4.49" y2="1.94" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#991146"/><stop offset="0" stop-color="#326b4e"/><stop offset=".02" stop-color="#3a685c"/><stop offset=".07" stop-color="#506180"/><stop offset=".13" stop-color="#645aa0"/><stop offset=".19" stop-color="#7554bc"/><stop offset=".26" stop-color="#8250d2"/><stop offset=".35" stop-color="#8d4ce3"/><stop offset=".45" stop-color="#944aee"/><stop offset=".6" stop-color="#9848f5"/><stop offset="1" stop-color="#9948f7"/></linearGradient><linearGradient id="未命名的渐变_11" x1="15.34" y1="6.67" x2="7.88" y2="10.98" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#33bc7a"/><stop offset=".45" stop-color="#32ba7a"/><stop offset=".61" stop-color="#2fb37c"/><stop offset=".73" stop-color="#29a87e"/><stop offset=".82" stop-color="#219782"/><stop offset=".9" stop-color="#168186"/><stop offset=".97" stop-color="#09668b"/><stop offset="1" stop-color="#03598e"/></linearGradient></defs><title>logo</title><rect class="cls-1" x="-143.14" y="-373.46" width="597.8" height="424.44"/><circle class="cls-2" cx="12.02" cy="1.83" r="1.33"/><circle class="cls-3" cx="12.02" cy="14.17" r="1.33"/><circle class="cls-4" cx="1.33" cy="8" r="1.33"/><path class="cls-5" d="M7.91 10h0a2.65 2.65.0 01-.23-3.74A1.75 1.75.0 017.91 6h0A2.66 2.66.0 014.4 6h0a1.81 1.81.0 01.24.24A2.65 2.65.0 014.4 10h0a2.62 2.62.0 00-.89 2 2.65 2.65.0 104.4-2z"/><path class="cls-6" d="M12.19 5.49a2.78 2.78.0 01-.5.11A2.64 2.64.0 018.76 3.5h0a2.65 2.65.0 10-2.6 3.17A2.6 2.6.0 007 6.53H7a2.65 2.65.0 013.44 2 2.94 2.94.0 010-.51 2.65 2.65.0 011.75-2.53z"/><path class="cls-7" d="M13 5.35a2.64 2.64.0 00-2.59 2.12h0a3 3 0 01-.08.32A2.65 2.65.0 017.54 9.58a2.86 2.86.0 00.37.41h0a2.63 2.63.0 01.9 2 2.84 2.84.0 01-.05.51 2.64 2.64.0 013.12-2.06l.32.08h0a2.6 2.6.0 00.84.14 2.65 2.65.0 100-5.3z"/></svg></span><span class=font-weight-bold>HugeGraph</span></a><div class="td-navbar-nav-scroll ml-md-auto" id=main_navbar><ul class="navbar-nav mt-2 mt-lg-0"><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/cn/docs/><i class='fas fa-book pr-2'></i><span>Documentation</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=https://github.com/apache/incubator-hugegraph target=_blank><i class='fab fa-github pr-2'></i><span>GitHub</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/cn/docs/download/download/><i class='fas fa-download pr-2'></i><span>Download</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/cn/community/><span>Community</span></a></li><li class="nav-item dropdown mr-4 d-none d-lg-block"><a class="nav-link dropdown-toggle" href=# id=navbarDropdown role=button data-toggle=dropdown aria-haspopup=true aria-expanded=false>中文</a><div class=dropdown-menu aria-labelledby=navbarDropdownMenuLink><a class=dropdown-item href=/docs/guides/>English</a></div></li></ul></div><div class="navbar-nav d-none d-lg-block"></div></nav></header><div class="container-fluid td-outer"><div class=td-main><div class="row flex-xl-nowrap"><main class="col-12 col-md-9 col-xl-8 pl-md-5" role=main><div class=td-content><div class="pageinfo pageinfo-primary d-print-none"><p>This is the multi-page printable view of this section.
<a href=# onclick="return print(),!1">Click here to print</a>.</p><p><a href=/cn/docs/guides/>Return to the regular view of this page</a>.</p></div><h1 class=title>GUIDES</h1><ul><li>1: <a href=#pg-dcb89d888ea6f4146ace522d76fe2776>HugeGraph Architecture Overview</a></li><li>2: <a href=#pg-3d0f9ef831ef5d7d11acfb09140359fa>HugeGraph Design Concepts</a></li><li>3: <a href=#pg-96a920d19e01666d95eded506d502ab4>HugeGraph Plugin 机制及插件扩展流程</a></li><li>4: <a href=#pg-2c9db416c8d78f898d52c91ec12535d4>Backup Restore</a></li><li>5: <a href=#pg-3465b699399f48689cdc6b5e59a10d69>FAQ</a></li><li>6: <a href=#pg-d54c862d45861ca39a945d90325e3909>报告安全问题</a></li></ul><div class=content></div></div><div class=td-content><h1 id=pg-dcb89d888ea6f4146ace522d76fe2776>1 - HugeGraph Architecture Overview</h1><h3 id=1-概述>1 概述</h3><p>作为一款通用的图数据库产品,HugeGraph 需具备图数据库的基本功能。HugeGraph 支持 OLTP 和 OLAP 两种图计算类型,其中 OLTP 实现了 <a href=https://tinkerpop.apache.org>Apache TinkerPop3</a> 框架,支持 <a href=https://tinkerpop.apache.org/gremlin.html>Gremlin</a><a href=https://en.wikipedia.org/wiki/Cypher>Cypher</a> 查询语言,拥有功能齐全的应用工具链,还提供了插件式后端存储驱动框架。</p><p>下面是 HugeGraph 的整体架构图:</p><div style=text-align:center><img src=/docs/images/design/architectural-revised.png alt=image></div><p>HugeGraph 包括三个层次的功能,分别是应用程序层、图引擎层和存储层。</p><ul><li>应用程序层:<ul><li><a href=/docs/quickstart/hugegraph-hubble/>Hubble</a>: 一站式可视化分析平台,平台涵盖了从数据建模,到数据快速导入,再到数据的在线、离线分析、以及图的统一管理的全过程,实现了图应用的全流程向导式操作。</li><li><a href=/docs/quickstart/hugegraph-loader/>Loader</a>: 数据导入组件,能够将多种数据源的数据转化为图的顶点和边并批量导入到图数据库中。</li><li><a href=/docs/quickstart/hugegraph-tools/>Tools</a>: 命令行工具,用于部署、管理和备份/恢复 HugeGraph 中的数据。</li><li><a href=/docs/quickstart/hugegraph-computer/>Computer</a>: 分布式图处理系统 (OLAP),它是 <a href=https://kowshik.github.io/JPregel/pregel_paper.pdf>Pregel</a> 的一个实现,可以运行在 Kubernetes 上。</li><li><a href=/docs/quickstart/hugegraph-client/>Client</a>: 使用 Java 编写的 HugeGraph 客户端,用户可以使用 Client 编写 Java 代码操作 HugeGraph,后续可根据需要提供 Python、Go、C++ 等多语言支持。</li></ul></li><li><a href=/docs/quickstart/hugegraph-server/>图引擎层</a><ul><li>REST Server: 提供 RESTful API 用于查询 Graph/Schema 等信息,支持 <a href=https://tinkerpop.apache.org/gremlin.html>Gremlin</a><a href=https://en.wikipedia.org/wiki/Cypher>Cypher</a> 查询语言,提供服务监控和运维的 APIs。</li><li>Graph Engine: 支持 OLTP 和 OLAP 两种图计算类型,其中 OLTP 实现了 <a href=https://tinkerpop.apache.org>Apache TinkerPop3</a> 框架。</li><li>Backend Interface: 实现将图数据存储到后端。</li></ul></li><li>存储层:<ul><li>Storage Backend: 支持多种内置存储后端 (RocksDB/MySQL/HBase/&mldr;),也允许用户无需更改现有源码的情况下扩展自定义后端。</li></ul></li></ul></div><div class=td-content style=page-break-before:always><h1 id=pg-3d0f9ef831ef5d7d11acfb09140359fa>2 - HugeGraph Design Concepts</h1><h3 id=1-property-graph>1. Property Graph</h3><p>常见的图数据表示模型有两种,分别是RDF(Resource Description Framework)模型和属性图(Property Graph)模型。
RDF和Property Graph都是最基础、最有名的图表示模式,都能够表示各种图的实体关系建模。
RDF是W3C标准,而Property Graph是工业标准,受到广大图数据库厂商的广泛支持。HugeGraph目前采用Property Graph。</p><p>HugeGraph对应的存储概念模型也是参考Property Graph而设计的,具体示例详见下图:(<em>此图为旧版设计已过时,请忽略它,后续更新</em></p><p><img src=/docs/images/design/PropertyGraph.png alt=image></p><p>在HugeGraph内部,每个顶点 / 边由唯一的 VertexId / EdgeId 标识,属性存储在对应点 / 边内部。而顶点与顶点之间的关系 / 映射则是通过边来存储的。</p><p>顶点属性值通过边指针方式存储时,如果要更新一个顶点特定的属性值直接通过覆盖写入即可,其弊端是冗余存储了VertexId;
如果要更新关系的属性需要通过read-and-modify方式,先读取所有属性,修改部分属性,然后再写入存储系统,更新效率较低。
从经验来看顶点属性的修改需求较多,而边的属性修改需求较少,例如PageRank和Graph Cluster等计算都需要频繁修改顶点的属性值。</p><h3 id=2-图分区方案>2. 图分区方案</h3><p>对于分布式图数据库而言,图的分区存储方式有两种:分别是边分割存储(Edge Cut)和点分割存储(Vertex Cut),如下图所示。
使用Edge Cut方式存储图时,任何一个顶点只会出现在一台机器上,而边可能分布在不同机器上,这种存储方式有可能导致边多次存储。
使用Vertex Cut方式存储图时,任何一条边只会出现在一台机器上,而每相同的一个点可能分布到不同机器上,这种存储方式可能会导致顶点多次存储。</p><p><img src=/docs/images/design/GraphCut.png alt=image></p><p>采用EdgeCut分区方案可以支持高性能的插入和更新操作,而VertexCut分区方案更适合静态图查询分析,因此EdgeCut适合OLTP图查询,VertexCut更适合OLAP的图查询。
HugeGraph目前采用EdgeCut的分区方案。</p><h3 id=3-vertexid-策略>3. VertexId 策略</h3><p>HugeGraph的Vertex支持三种ID策略,在同一个图数据库中不同的VertexLabel可以使用不同的Id策略,目前HugeGraph支持的Id策略分别是:</p><ul><li>自动生成(AUTOMATIC):使用Snowflake算法自动生成全局唯一Id,Long类型;</li><li>主键(PRIMARY_KEY):通过VertexLabel+PrimaryKeyValues生成Id,String类型;</li><li>自定义(CUSTOMIZE_STRING|CUSTOMIZE_NUMBER):用户自定义Id,分为String和Long类型两种,需自己保证Id的唯一性;</li></ul><p>默认的Id策略是AUTOMATIC,如果用户调用primaryKeys()方法并设置了正确的PrimaryKeys,则自动启用PRIMARY_KEY策略。
启用PRIMARY_KEY策略后HugeGraph能根据PrimaryKeys实现数据去重。</p><ol><li>AUTOMATIC ID策略</li></ol><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#000>schema</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>useAutomaticId</span><span style=color:#ce5c00;font-weight:700>()</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>properties</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>create</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>,</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;marko&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>18</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;Beijing&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span></code></pre></div><ol start=2><li>PRIMARY_KEY ID策略</li></ol><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#000>schema</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>usePrimaryKeyId</span><span style=color:#ce5c00;font-weight:700>()</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>properties</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>primaryKeys</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>create</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>,</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;marko&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>18</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;Beijing&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span></code></pre></div><ol start=3><li>CUSTOMIZE_STRING ID策略</li></ol><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#000>schema</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>useCustomizeStringId</span><span style=color:#ce5c00;font-weight:700>()</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>properties</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>create</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>id</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;123456&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;marko&#34;</span><span style=color:#ce5c00;font-weight:700>,</span><span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>18</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;Beijing&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span></code></pre></div><ol start=4><li>CUSTOMIZE_NUMBER ID策略</li></ol><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#000>schema</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>useCustomizeNumberId</span><span style=color:#ce5c00;font-weight:700>()</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>properties</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>)</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>create</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;person&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>id</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>123456</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;marko&#34;</span><span style=color:#ce5c00;font-weight:700>,</span><span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>18</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;city&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;Beijing&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span></code></pre></div><p>如果用户需要Vertex去重,有三种方案分别是:</p><ol><li>采用PRIMARY_KEY策略,自动覆盖,适合大数据量批量插入,用户无法知道是否发生了覆盖行为</li><li>采用AUTOMATIC策略,read-and-modify,适合小数据量插入,用户可以明确知道是否发生覆盖</li><li>采用CUSTOMIZE_STRING或CUSTOMIZE_NUMBER策略,用户自己保证唯一</li></ol><h3 id=4-edgeid-策略>4. EdgeId 策略</h3><p>HugeGraph的EdgeId是由<code>srcVertexId</code>+<code>edgeLabel</code>+<code>sortKey</code>+<code>tgtVertexId</code>四部分组合而成。其中<code>sortKey</code>是HugeGraph的一个重要概念。
在Edge中加入<code>sortKey</code>作为Edge的唯一标识的原因有两个:</p><ol><li>如果两个顶点之间存在多条相同Label的边可通过<code>sortKey</code>来区分</li><li>对于SuperNode的节点,可以通过<code>sortKey</code>来排序截断。</li></ol><p>由于EdgeId是由<code>srcVertexId</code>+<code>edgeLabel</code>+<code>sortKey</code>+<code>tgtVertexId</code>四部分组合,多次插入相同的Edge时HugeGraph会自动覆盖以实现去重。
需要注意的是如果批量插入模式下Edge的属性也将会覆盖。</p><p>另外由于HugeGraph的EdgeId采用自动去重策略,对于self-loop(一个顶点存在一条指向自身的边)的情况下HugeGraph认为仅有一条边,对于采用AUTOMATIC策略的图数据库(例如TitianDB
)则会认为该图存在两条边。</p><blockquote><p>HugeGraph的边仅支持有向边,无向边可以创建Out和In两条边来实现。</p></blockquote><h3 id=5-hugegraph-transaction-overview>5. HugeGraph transaction overview</h3><h5 id=tinkerpop事务概述>TinkerPop事务概述</h5><p>TinkerPop transaction事务是指对数据库执行操作的工作单元,一个事务内的一组操作要么执行成功,要么全部失败。
详细介绍请参考TinkerPop官方文档:http://tinkerpop.apache.org/docs/current/reference/#transactions</p><h5 id=tinkerpop事务操作接口>TinkerPop事务操作接口</h5><ul><li>open 打开事务</li><li>commit 提交事务</li><li>rollback 回滚事务</li><li>close 关闭事务</li></ul><h5 id=tinkerpop事务规范>TinkerPop事务规范</h5><ul><li>事务必须显式提交后才可生效(未提交时修改操作只有本事务内查询可看到)</li><li>事务必须打开之后才可提交或回滚</li><li>如果事务设置自动打开则无需显式打开(默认方式),如果设置手动打开则必须显式打开</li><li>可设置事务关闭时:自动提交、自动回滚(默认方式)、手动(禁止显式关闭)等3种模式</li><li>事务在提交或回滚后必须是关闭状态</li><li>事务在查询后必须是打开状态</li><li>事务(非threaded tx)必须线程隔离,多线程操作同一事务互不影响</li></ul><p>更多事务规范用例见:<a href=https://github.com/apache/tinkerpop/blob/master/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionTest.java>Transaction Test</a></p><h5 id=hugegraph事务实现>HugeGraph事务实现</h5><ul><li>一个事务中所有的操作要么成功要么失败</li><li>一个事务只能读取到另外一个事务已提交的内容(Read committed)</li><li>所有未提交的操作均能在本事务中查询出来,包括:<ul><li>增加顶点能够查询出该顶点</li><li>删除顶点能够过滤掉该顶点</li><li>删除顶点能够过滤掉该顶点相关边</li><li>增加边能够查询出该边</li><li>删除边能够过滤掉该边</li><li>增加/修改(顶点、边)属性能够在查询时生效</li><li>删除(顶点、边)属性能够在查询时生效</li></ul></li><li>所有未提交的操作在事务回滚后均失效,包括:<ul><li>顶点、边的增加、删除</li><li>属性的增加/修改、删除</li></ul></li></ul><p>示例:一个事务无法读取另一个事务未提交的内容</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>testUncommittedTx</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#204a87;font-weight:700>throws</span> <span style=color:#000>InterruptedException</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>CountDownLatch</span> <span style=color:#000>latchUncommit</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>CountDownLatch</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>1</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>CountDownLatch</span> <span style=color:#000>latchRollback</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>CountDownLatch</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>1</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>Thread</span> <span style=color:#000>thread</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>Thread</span><span style=color:#ce5c00;font-weight:700>(()</span> <span style=color:#ce5c00;font-weight:700>-&gt;</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// this is a new transaction in the new thread
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>tx</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>open</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>System</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>out</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>println</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;current transaction operations&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>Vertex</span> <span style=color:#000>james</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;author&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;id&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>1</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;James Gosling&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;age&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>62</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;lived&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;Canadian&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#000>Vertex</span> <span style=color:#000>java</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>T</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>label</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;language&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;name&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#4e9a06>&#34;java&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;versions&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>Arrays</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>asList</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>6</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>7</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>8</span><span style=color:#ce5c00;font-weight:700>));</span>
</span></span><span style=display:flex><span> <span style=color:#000>james</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>addEdge</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;created&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>java</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// we can query the uncommitted records in the current transaction
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#000>System</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>out</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>println</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;current transaction assert&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertices</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>==</span> <span style=color:#204a87;font-weight:700>true</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>edges</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>==</span> <span style=color:#204a87;font-weight:700>true</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>latchUncommit</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>countDown</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>try</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#000>latchRollback</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>await</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span> <span style=color:#204a87;font-weight:700>catch</span> <span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>InterruptedException</span> <span style=color:#000>e</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>throw</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>RuntimeException</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>e</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>System</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>out</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>println</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;current transaction rollback&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>tx</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>rollback</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>});</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>thread</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>start</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// query none result in other transaction when not commit()
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#000>latchUncommit</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>await</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#000>System</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>out</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>println</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;other transaction assert for uncommitted&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#ce5c00;font-weight:700>!</span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertices</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#ce5c00;font-weight:700>!</span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>edges</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#000>latchRollback</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>countDown</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#000>thread</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>join</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// query none result in other transaction after rollback()
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#000>System</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>out</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>println</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;other transaction assert for rollback&#34;</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#ce5c00;font-weight:700>!</span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>vertices</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>assert</span> <span style=color:#ce5c00;font-weight:700>!</span><span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>edges</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>hasNext</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h5 id=事务实现原理>事务实现原理</h5><ul><li>服务端内部通过将事务与线程绑定实现隔离(ThreadLocal)</li><li>本事务未提交的内容按照时间顺序覆盖老数据以供本事务查询最新版本数据</li><li>底层依赖后端数据库保证事务原子性操作(如Cassandra/RocksDB的batch接口均保证原子性)</li></ul><h6 id=注意><em>注意</em></h6><blockquote><p>RESTful API暂时未暴露事务接口</p></blockquote><blockquote><p>TinkerPop API允许打开事务,请求完成时会自动关闭(Gremlin Server强制关闭)</p></blockquote></div><div class=td-content style=page-break-before:always><h1 id=pg-96a920d19e01666d95eded506d502ab4>3 - HugeGraph Plugin 机制及插件扩展流程</h1><h3 id=背景>背景</h3><ol><li>HugeGraph 不仅开源开放,而且要做到简单易用,一般用户无需更改源码也能轻松增加插件扩展功能。</li><li>HugeGraph 支持多种内置存储后端,也允许用户无需更改现有源码的情况下扩展自定义后端。</li><li>HugeGraph 支持全文检索,全文检索功能涉及到各语言分词,目前已内置 8 种中文分词器,也允许用户无需更改现有源码的情况下扩展自定义分词器。</li></ol><h3 id=可扩展维度>可扩展维度</h3><p>目前插件方式提供如下几个维度的扩展项:</p><ul><li>后端存储</li><li>序列化器</li><li>自定义配置项</li><li>分词器</li></ul><h3 id=插件实现机制>插件实现机制</h3><ol><li>HugeGraph 提供插件接口 HugeGraphPlugin,通过 Java SPI 机制支持插件化</li><li>HugeGraph 提供了 4 个扩展项注册函数:<code>registerOptions()</code><code>registerBackend()</code><code>registerSerializer()</code><code>registerAnalyzer()</code></li><li>插件实现者实现相应的 Options、Backend、Serializer 或 Analyzer 的接口</li><li>插件实现者实现 HugeGraphPlugin 接口的<code>register()</code>方法,在该方法中注册上述第 3 点所列的具体实现类,并打成 jar 包</li><li>插件使用者将 jar 包放在 HugeGraph Server 安装目录的<code>plugins</code>目录下,修改相关配置项为插件自定义值,重启即可生效</li></ol><h3 id=插件实现流程实例>插件实现流程实例</h3><h4 id=1-新建一个-maven-项目>1 新建一个 maven 项目</h4><h5 id=11-项目名称取名hugegraph-plugin-demo>1.1 项目名称取名:hugegraph-plugin-demo</h5><h5 id=12-添加hugegraph-core-jar-包依赖>1.2 添加<code>hugegraph-core</code> Jar 包依赖</h5><p>maven pom.xml 详细内容如下:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#8f5902;font-style:italic>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>&lt;project</span> <span style=color:#c4a000>xmlns=</span><span style=color:#4e9a06>&#34;http://maven.apache.org/POM/4.0.0&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#c4a000>xmlns:xsi=</span><span style=color:#4e9a06>&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#c4a000>xsi:schemaLocation=</span><span style=color:#4e9a06>&#34;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&#34;</span><span style=color:#204a87;font-weight:700>&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;modelVersion&gt;</span>4.0.0<span style=color:#204a87;font-weight:700>&lt;/modelVersion&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;groupId&gt;</span>org.apache.hugegraph<span style=color:#204a87;font-weight:700>&lt;/groupId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;artifactId&gt;</span>hugegraph-plugin-demo<span style=color:#204a87;font-weight:700>&lt;/artifactId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;version&gt;</span>1.0.0<span style=color:#204a87;font-weight:700>&lt;/version&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;packaging&gt;</span>jar<span style=color:#204a87;font-weight:700>&lt;/packaging&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;name&gt;</span>hugegraph-plugin-demo<span style=color:#204a87;font-weight:700>&lt;/name&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;dependencies&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;dependency&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;groupId&gt;</span>org.apache.hugegraph<span style=color:#204a87;font-weight:700>&lt;/groupId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;artifactId&gt;</span>hugegraph-core<span style=color:#204a87;font-weight:700>&lt;/artifactId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;version&gt;</span>${project.version}<span style=color:#204a87;font-weight:700>&lt;/version&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;/dependency&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&lt;/dependencies&gt;</span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>&lt;/project&gt;</span>
</span></span></code></pre></div><h4 id=2-实现扩展功能>2 实现扩展功能</h4><h5 id=21-扩展自定义后端>2.1 扩展自定义后端</h5><h6 id=211-实现接口-backendstoreprovider>2.1.1 实现接口 BackendStoreProvider</h6><ul><li>可实现接口:<code>org.apache.hugegraph.backend.store.BackendStoreProvider</code></li><li>或者继承抽象类:<code>org.apache.hugegraph.backend.store.AbstractBackendStoreProvider</code></li></ul><p>以 RocksDB 后端 RocksDBStoreProvider 为例:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>class</span> <span style=color:#000>RocksDBStoreProvider</span> <span style=color:#204a87;font-weight:700>extends</span> <span style=color:#000>AbstractBackendStoreProvider</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>protected</span> <span style=color:#000>String</span> <span style=color:#000>database</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#204a87;font-weight:700>this</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>graph</span><span style=color:#ce5c00;font-weight:700>().</span><span style=color:#c4a000>toLowerCase</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>protected</span> <span style=color:#000>BackendStore</span> <span style=color:#000>newSchemaStore</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>String</span> <span style=color:#000>store</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>RocksDBSchemaStore</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#204a87;font-weight:700>this</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#204a87;font-weight:700>this</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>database</span><span style=color:#ce5c00;font-weight:700>(),</span> <span style=color:#000>store</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>protected</span> <span style=color:#000>BackendStore</span> <span style=color:#000>newGraphStore</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>String</span> <span style=color:#000>store</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>RocksDBGraphStore</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#204a87;font-weight:700>this</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#204a87;font-weight:700>this</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>database</span><span style=color:#ce5c00;font-weight:700>(),</span> <span style=color:#000>store</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>type</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#4e9a06>&#34;rocksdb&#34;</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>version</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#4e9a06>&#34;1.0&#34;</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h6 id=212-实现接口-backendstore>2.1.2 实现接口 BackendStore</h6><p>BackendStore 接口定义如下:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>interface</span> <span style=color:#000>BackendStore</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Store name
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>store</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Database name
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>database</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Get the parent provider
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendStoreProvider</span> <span style=color:#000>provider</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Open/close database
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>open</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeConfig</span> <span style=color:#000>config</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>close</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Initialize/clear database
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>init</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>clear</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Add/delete data
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>mutate</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>BackendMutation</span> <span style=color:#000>mutation</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Query data
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>Iterator</span><span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>BackendEntry</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>query</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>Query</span> <span style=color:#000>query</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Transaction
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>beginTx</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>commitTx</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>rollbackTx</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Get metadata by key
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>R</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>R</span> <span style=color:#000>metadata</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeType</span> <span style=color:#000>type</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>String</span> <span style=color:#000>meta</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>Object</span><span style=color:#ce5c00;font-weight:700>[]</span> <span style=color:#000>args</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Backend features
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendFeatures</span> <span style=color:#000>features</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#8f5902;font-style:italic>// Generate an id for a specific type
</span></span></span><span style=display:flex><span><span style=color:#8f5902;font-style:italic></span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>Id</span> <span style=color:#000>nextId</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeType</span> <span style=color:#000>type</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h6 id=213-扩展自定义序列化器>2.1.3 扩展自定义序列化器</h6><p>序列化器必须继承抽象类:<code>org.apache.hugegraph.backend.serializer.AbstractSerializer</code>(<code>implements GraphSerializer, SchemaSerializer</code>)
主要接口的定义如下:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>interface</span> <span style=color:#000>GraphSerializer</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeVertex</span> <span style=color:#000>vertex</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeVertexProperty</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeVertexProperty</span><span style=color:#ce5c00;font-weight:700>&lt;?&gt;</span> <span style=color:#000>prop</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>HugeVertex</span> <span style=color:#000>readVertex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeEdge</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeEdge</span> <span style=color:#000>edge</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeEdgeProperty</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeEdgeProperty</span><span style=color:#ce5c00;font-weight:700>&lt;?&gt;</span> <span style=color:#000>prop</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>HugeEdge</span> <span style=color:#000>readEdge</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeIndex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeIndex</span> <span style=color:#000>index</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>HugeIndex</span> <span style=color:#000>readIndex</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>ConditionQuery</span> <span style=color:#000>query</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeId</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeType</span> <span style=color:#000>type</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>Id</span> <span style=color:#000>id</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>Query</span> <span style=color:#000>writeQuery</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>Query</span> <span style=color:#000>query</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>interface</span> <span style=color:#000>SchemaSerializer</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeVertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>VertexLabel</span> <span style=color:#000>vertexLabel</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>VertexLabel</span> <span style=color:#000>readVertexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeEdgeLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>EdgeLabel</span> <span style=color:#000>edgeLabel</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>EdgeLabel</span> <span style=color:#000>readEdgeLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writePropertyKey</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>PropertyKey</span> <span style=color:#000>propertyKey</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>PropertyKey</span> <span style=color:#000>readPropertyKey</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>writeIndexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>IndexLabel</span> <span style=color:#000>indexLabel</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>IndexLabel</span> <span style=color:#000>readIndexLabel</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>HugeGraph</span> <span style=color:#000>graph</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>BackendEntry</span> <span style=color:#000>entry</span><span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h6 id=214-扩展自定义配置项>2.1.4 扩展自定义配置项</h6><p>增加自定义后端时,可能需要增加新的配置项,实现流程主要包括:</p><ul><li>增加配置项容器类,并实现接口<code>org.apache.hugegraph.config.OptionHolder</code></li><li>提供单例方法<code>public static OptionHolder instance()</code>,并在对象初始化时调用方法<code>OptionHolder.registerOptions()</code></li><li>增加配置项声明,单值配置项类型为<code>ConfigOption</code>、多值配置项类型为<code>ConfigListOption</code></li></ul><p>以 RocksDB 配置项定义为例:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>class</span> <span style=color:#000>RocksDBOptions</span> <span style=color:#204a87;font-weight:700>extends</span> <span style=color:#000>OptionHolder</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>private</span> <span style=color:#000>RocksDBOptions</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>super</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>private</span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>volatile</span> <span style=color:#000>RocksDBOptions</span> <span style=color:#000>instance</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>synchronized</span> <span style=color:#000>RocksDBOptions</span> <span style=color:#000>instance</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>if</span> <span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>instance</span> <span style=color:#ce5c00;font-weight:700>==</span> <span style=color:#204a87;font-weight:700>null</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#000>instance</span> <span style=color:#ce5c00;font-weight:700>=</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>RocksDBOptions</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#000>instance</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>registerOptions</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#000>instance</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>ConfigOption</span><span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>String</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>DATA_PATH</span> <span style=color:#ce5c00;font-weight:700>=</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>ConfigOption</span><span style=color:#ce5c00;font-weight:700>&lt;&gt;(</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;rocksdb.data_path&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;The path for storing data of RocksDB.&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#000>disallowEmpty</span><span style=color:#ce5c00;font-weight:700>(),</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;rocksdb-data&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>ConfigOption</span><span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>String</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>WAL_PATH</span> <span style=color:#ce5c00;font-weight:700>=</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>ConfigOption</span><span style=color:#ce5c00;font-weight:700>&lt;&gt;(</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;rocksdb.wal_path&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;The path for storing WAL of RocksDB.&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#000>disallowEmpty</span><span style=color:#ce5c00;font-weight:700>(),</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;rocksdb-data&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>static</span> <span style=color:#204a87;font-weight:700>final</span> <span style=color:#000>ConfigListOption</span><span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>String</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>DATA_DISKS</span> <span style=color:#ce5c00;font-weight:700>=</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>ConfigListOption</span><span style=color:#ce5c00;font-weight:700>&lt;&gt;(</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;rocksdb.data_disks&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>false</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;The optimized disks for storing data of RocksDB. &#34;</span> <span style=color:#ce5c00;font-weight:700>+</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;The format of each element: `STORE/TABLE: /path/to/disk`.&#34;</span> <span style=color:#ce5c00;font-weight:700>+</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;Allowed keys are [graph/vertex, graph/edge_out, graph/edge_in, &#34;</span> <span style=color:#ce5c00;font-weight:700>+</span>
</span></span><span style=display:flex><span> <span style=color:#4e9a06>&#34;graph/secondary_index, graph/range_index]&#34;</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>null</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#000>String</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>class</span><span style=color:#ce5c00;font-weight:700>,</span>
</span></span><span style=display:flex><span> <span style=color:#000>ImmutableList</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>of</span><span style=color:#ce5c00;font-weight:700>()</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>);</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h5 id=22-扩展自定义分词器>2.2 扩展自定义分词器</h5><p>分词器需要实现接口<code>org.apache.hugegraph.analyzer.Analyzer</code>,以实现一个 SpaceAnalyzer 空格分词器为例。</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>package</span> <span style=color:#000>org.apache.hugegraph.plugin</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>import</span> <span style=color:#000>java.util.Arrays</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>import</span> <span style=color:#000>java.util.HashSet</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>import</span> <span style=color:#000>java.util.Set</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>import</span> <span style=color:#000>org.apache.hugegraph.analyzer.Analyzer</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>class</span> <span style=color:#000>SpaceAnalyzer</span> <span style=color:#204a87;font-weight:700>implements</span> <span style=color:#000>Analyzer</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>Set</span><span style=color:#ce5c00;font-weight:700>&lt;</span><span style=color:#000>String</span><span style=color:#ce5c00;font-weight:700>&gt;</span> <span style=color:#000>segment</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>String</span> <span style=color:#000>text</span><span style=color:#ce5c00;font-weight:700>)</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#204a87;font-weight:700>new</span> <span style=color:#000>HashSet</span><span style=color:#ce5c00;font-weight:700>&lt;&gt;(</span><span style=color:#000>Arrays</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>asList</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#000>text</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>split</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34; &#34;</span><span style=color:#ce5c00;font-weight:700>)));</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h4 id=3-实现插件接口并进行注册>3. 实现插件接口,并进行注册</h4><p>插件注册入口为<code>HugeGraphPlugin.register()</code>,自定义插件必须实现该接口方法,在其内部注册上述定义好的扩展项。
接口<code>org.apache.hugegraph.plugin.HugeGraphPlugin</code>定义如下:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>interface</span> <span style=color:#000>HugeGraphPlugin</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>name</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>register</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>supportsMinVersion</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>supportsMaxVersion</span><span style=color:#ce5c00;font-weight:700>();</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><p>并且 HugeGraphPlugin 提供了 4 个静态方法用于注册扩展项:</p><ul><li>registerOptions(String name, String classPath):注册配置项</li><li>registerBackend(String name, String classPath):注册后端(BackendStoreProvider)</li><li>registerSerializer(String name, String classPath):注册序列化器</li><li>registerAnalyzer(String name, String classPath):注册分词器</li></ul><p>下面以注册 SpaceAnalyzer 分词器为例:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#204a87;font-weight:700>package</span> <span style=color:#000>org.apache.hugegraph.plugin</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>class</span> <span style=color:#000>DemoPlugin</span> <span style=color:#204a87;font-weight:700>implements</span> <span style=color:#000>HugeGraphPlugin</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#000>String</span> <span style=color:#000>name</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>return</span> <span style=color:#4e9a06>&#34;demo&#34;</span><span style=color:#ce5c00;font-weight:700>;</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#5c35cc;font-weight:700>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>public</span> <span style=color:#204a87;font-weight:700>void</span> <span style=color:#000>register</span><span style=color:#ce5c00;font-weight:700>()</span> <span style=color:#ce5c00;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#000>HugeGraphPlugin</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>registerAnalyzer</span><span style=color:#ce5c00;font-weight:700>(</span><span style=color:#4e9a06>&#34;demo&#34;</span><span style=color:#ce5c00;font-weight:700>,</span> <span style=color:#000>SpaceAnalyzer</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>class</span><span style=color:#ce5c00;font-weight:700>.</span><span style=color:#c4a000>getName</span><span style=color:#ce5c00;font-weight:700>());</span>
</span></span><span style=display:flex><span> <span style=color:#ce5c00;font-weight:700>}</span>
</span></span><span style=display:flex><span><span style=color:#ce5c00;font-weight:700>}</span>
</span></span></code></pre></div><h4 id=4-配置-spi-入口>4. 配置 SPI 入口</h4><ol><li>确保 services 目录存在:hugegraph-plugin-demo/resources/META-INF/services</li><li>在 services 目录下建立文本文件:org.apache.hugegraph.plugin.HugeGraphPlugin</li><li>文件内容如下:org.apache.hugegraph.plugin.DemoPlugin</li></ol><h4 id=5-打-jar-包>5. 打 Jar 包</h4><p>通过 maven 打包,在项目目录下执行命令<code>mvn package</code>,在 target 目录下会生成 Jar 包文件。
使用时将该 Jar 包拷到<code>plugins</code>目录,重启服务即可生效。</p></div><div class=td-content style=page-break-before:always><h1 id=pg-2c9db416c8d78f898d52c91ec12535d4>4 - Backup Restore</h1><h2 id=描述>描述</h2><p>Backup 和 Restore 是备份图和恢复图的功能。备份和恢复的数据包括元数据(schema)和图数据(vertex 和 edge)。</p><h4 id=backup>Backup</h4><p>将 HugeGraph 系统中的一张图的元数据和图数据以 JSON 格式导出。</p><h4 id=restore>Restore</h4><p>将 Backup 导出的JSON格式的数据,重新导入到 HugeGraph 系统中的一个图中。</p><p>Restore 有两种模式:</p><ul><li>Restoring 模式,将 Backup 导出的元数据和图数据原封不动的恢复到 HugeGraph 系统中。可用于图的备份和恢复,一般目标图是新图(没有元数据和图数据)。比如:<ul><li>系统升级,先备份图,然后升级系统,最后将图恢复到新的系统中</li><li>图迁移,从一个 HugeGraph 系统中,使用 Backup 功能将图导出,然后使用 Restore 功能将图导入另一个 HugeGraph 系统中</li></ul></li><li>Merging 模式,将 Backup 导出的元数据和图数据导入到另一个已经存在元数据或者图数据的图中,过程中元数据的 ID 可能发生改变,顶点和边的 ID 也会发生相应变化。<ul><li>可用于合并图</li></ul></li></ul><h2 id=使用方法>使用方法</h2><p>可以使用<a href=/docs/quickstart/hugegraph-tools>hugegraph-tools</a>进行图的备份和恢复。</p><h4 id=backup-1>Backup</h4><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>bin/hugegraph backup -t all -d data
</span></span></code></pre></div><p>该命令将 http://127.0.0.1 的 hugegraph 图的全部元数据和图数据备份到data目录下。</p><blockquote><p>Backup 在三种图模式下都可以正常工作</p></blockquote><h4 id=restore-1>Restore</h4><p>Restore 有两种模式: RESTORING 和 MERGING,备份之前首先要根据需要设置图模式。</p><h5 id=步骤1查看并设置图模式>步骤1:查看并设置图模式</h5><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>bin/hugegraph graph-mode-get
</span></span></code></pre></div><p>该命令用于查看当前图模式,包括:NONE、RESTORING、MERGING。</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>bin/hugegraph graph-mode-set -m RESTORING
</span></span></code></pre></div><p>该命令用于设置图模式,Restore 之前可以设置成 RESTORING 或者 MERGING 模式,例子中设置成 RESTORING。</p><h5 id=步骤2restore-数据>步骤2:Restore 数据</h5><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>bin/hugegraph restore -t all -d data
</span></span></code></pre></div><p>该命令将data目录下的全部元数据和图数据重新导入到 http://127.0.0.1 的 hugegraph 图中。</p><h5 id=步骤3恢复图模式>步骤3:恢复图模式</h5><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>bin/hugegraph graph-mode-set -m NONE
</span></span></code></pre></div><p>该命令用于恢复图模式为 NONE。</p><p>至此,一次完整的图备份和图恢复流程结束。</p><h4 id=帮助>帮助</h4><p>备份和恢复命令的详细使用方式可以参考<a href=/docs/quickstart/hugegraph-tools>hugegraph-tools文档</a></p><h2 id=backuprestore使用和实现的api说明>Backup/Restore使用和实现的API说明</h2><h4 id=backup-2>Backup</h4><p>Backup 使用<code>元数据</code><code>图数据</code>的相应的 list(GET) API 导出,并未增加新的 API。</p><h4 id=restore-2>Restore</h4><p>Restore 使用<code>元数据</code><code>图数据</code>的相应的 create(POST) API 导入,并未增加新的 API。</p><p>Restore 时存在两种不同的模式: Restoring 和 Merging,另外,还有常规模式 NONE(默认),区别如下:</p><ul><li>None 模式,元数据和图数据的写入属于正常状态,可参见功能说明。特别的:<ul><li>元数据(schema)创建时不允许指定 ID</li><li>图数据(vertex)在 id strategy 为 Automatic 时,不允许指定 ID</li></ul></li><li>Restoring 模式,恢复到一个新图中,特别的:<ul><li>元数据(schema)创建时允许指定 ID</li><li>图数据(vertex)在 id strategy 为 Automatic 时,允许指定 ID</li></ul></li><li>Merging 模式,合并到一个已存在元数据和图数据的图中,特别的:<ul><li>元数据(schema)创建时不允许指定 ID</li><li>图数据(vertex)在 id strategy 为 Automatic 时,允许指定 ID</li></ul></li></ul><p>正常情况下,图模式为 None,当需要 Restore 图时,需要根据需要临时修改图模式为 Restoring 模式或者 Merging 模式,并在完成 Restore 时,恢复图模式为 None。</p><p>实现的设置图模式的 RESTful API 如下:</p><h5 id=查看某个图的模式-该操作需要管理员权限>查看某个图的模式. <strong>该操作需要管理员权限</strong></h5><h6 id=method--url>Method & Url</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>GET http://localhost:8080/graphs/{graph}/mode
</span></span></code></pre></div><h6 id=response-status>Response Status</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span><span style=color:#0000cf;font-weight:700>200</span>
</span></span></code></pre></div><h6 id=response-body>Response Body</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span><span style=color:#000;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&#34;mode&#34;</span><span style=color:#000;font-weight:700>:</span> <span style=color:#4e9a06>&#34;NONE&#34;</span>
</span></span><span style=display:flex><span><span style=color:#000;font-weight:700>}</span>
</span></span></code></pre></div><blockquote><p>合法的图模式包括:NONE,RESTORING,MERGING</p></blockquote><h5 id=设置某个图的模式-该操作需要管理员权限>设置某个图的模式. <strong>该操作需要管理员权限</strong></h5><h6 id=method--url-1>Method & Url</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>PUT http://localhost:8080/graphs/{graph}/mode
</span></span></code></pre></div><h6 id=request-body>Request Body</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>&#34;RESTORING&#34;
</span></span></code></pre></div><blockquote><p>合法的图模式包括:NONE,RESTORING,MERGING</p></blockquote><h6 id=response-status-1>Response Status</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span><span style=color:#0000cf;font-weight:700>200</span>
</span></span></code></pre></div><h6 id=response-body-1>Response Body</h6><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span><span style=color:#000;font-weight:700>{</span>
</span></span><span style=display:flex><span> <span style=color:#204a87;font-weight:700>&#34;mode&#34;</span><span style=color:#000;font-weight:700>:</span> <span style=color:#4e9a06>&#34;RESTORING&#34;</span>
</span></span><span style=display:flex><span><span style=color:#000;font-weight:700>}</span>
</span></span></code></pre></div></div><div class=td-content style=page-break-before:always><h1 id=pg-3465b699399f48689cdc6b5e59a10d69>5 - FAQ</h1><ul><li><p>如何选择后端存储? 选 RocksDB 还是 Cassandra 还是 Hbase 还是 Mysql?</p><p>根据你的具体需要来判断, 一般单机或数据量 &lt; 100 亿推荐 RocksDB, 其他推荐使用分布式存储的后端集群</p></li><li><p>启动服务时提示:<code>xxx (core dumped) xxx</code></p><p>请检查JDK版本是否为 Java11 (至少是Java8)</p></li><li><p>启动服务成功了,但是操作图时有类似于"无法连接到后端或连接未打开"的提示</p><p>第一次启动服务前,需要先使用<code>init-store</code>初始化后端,后续版本会将提示得更清晰直接。</p></li><li><p>所有的后端在使用前都需要执行<code>init-store</code>吗,序列化的选择可以随意填写么?</p><p>除了<code>memory</code>不需要,其他后端均需要,如:<code>cassandra</code><code>hbase</code><code>rocksdb</code>等,序列化需一一对应不可随意填写。</p></li><li><p>执行<code>init-store</code>报错:<code>Exception in thread "main" java.lang.UnsatisfiedLinkError: /tmp/librocksdbjni3226083071221514754.so: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.10' not found (required by /tmp/librocksdbjni3226083071221514754.so)</code></p><p>RocksDB需要 gcc 4.3.0 (GLIBCXX_3.4.10) 及以上版本</p></li><li><p>执行<code>init-store.sh</code>时报错:<code>NoHostAvailableException</code></p><p><code>NoHostAvailableException</code> 是指无法连接到<code>Cassandra</code>服务,如果确定是要使用<code>cassandra</code>后端,请先安装并启动这个服务。至于这个提示本身可能不够直白,我们会更新到文档进行说明的。</p></li><li><p><code>bin</code>目录下包含<code>start-hugegraph.sh</code><code>start-restserver.sh</code><code>start-gremlinserver.sh</code>三个似乎与启动有关的脚本,到底该使用哪个</p><p>自0.3.3版本以来,已经把 GremlinServer 和 RestServer 合并为 HugeGraphServer 了,使用<code>start-hugegraph.sh</code>启动即可,后两个在后续版本会被删掉。</p></li><li><p>配置了两个图,名字是<code>hugegraph</code><code>hugegraph1</code>,而启动服务的命令是<code>start-hugegraph.sh</code>,是只打开了<code>hugegraph</code>这个图吗</p><p><code>start-hugegraph.sh</code>会打开所有<code>gremlin-server.yaml</code><code>graphs</code>下的图,这二者并无名字上的直接关系</p></li><li><p>服务启动成功后,使用<code>curl</code>查询所有顶点时返回乱码</p><p>服务端返回的批量顶点/边是压缩(gzip)过的,可以使用管道重定向至 <code>gunzip</code> 进行解压(<code>curl http://example | gunzip</code>),也可以用<code>Firefox</code><code>postman</code>或者<code>Chrome</code>浏览器的<code>restlet</code>插件发请求,会自动解压缩响应数据。</p></li><li><p>使用顶点Id通过<code>RESTful API</code>查询顶点时返回空,但是顶点确实是存在的</p><p>检查顶点Id的类型,如果是字符串类型,<code>API</code><code>url</code>中的id部分需要加上双引号,数字类型则不用加。</p></li><li><p>已经根据需要给顶点Id加上了双引号,但是通过<code>RESTful API</code>查询顶点时仍然返回空</p><p>检查顶点id中是否包含<code>+</code><code>空格</code><code>/</code><code>?</code><code>%</code><code>&</code><code>=</code>这些URL的保留字符,如果存在则需要进行编码。下表给出了编码值:</p><div class=highlight><pre tabindex=0 style=background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>特殊字符 | 编码值
</span></span><span style=display:flex><span>--------| ----
</span></span><span style=display:flex><span>+ | %2B
</span></span><span style=display:flex><span>空格 | %20
</span></span><span style=display:flex><span>/ | %2F
</span></span><span style=display:flex><span>? | %3F
</span></span><span style=display:flex><span>% | %25
</span></span><span style=display:flex><span># | %23
</span></span><span style=display:flex><span>&amp; | %26
</span></span><span style=display:flex><span>= | %3D
</span></span></code></pre></div></li><li><p>查询某一类别的顶点或边(<code>query by label</code>)时提示超时</p><p>由于属于某一label的数据量可能比较多,请加上limit限制。</p></li><li><p>通过<code>RESTful API</code>操作图是可以的,但是发送<code>Gremlin</code>语句就报错:<code>Request Failed(500)</code></p><p>可能是<code>GremlinServer</code>的配置有误,检查<code>gremlin-server.yaml</code><code>host</code><code>port</code>是否与<code>rest-server.properties</code><code>gremlinserver.url</code>匹配,如不匹配则修改,然后重启服务。</p></li><li><p>使用<code>Loader</code>导数据出现<code>Socket Timeout</code>异常,然后导致<code>Loader</code>中断</p><p>持续地导入数据会使<code>Server</code>的压力过大,然后导致有些请求超时。可以通过调整<code>Loader</code>的参数来适当缓解<code>Server</code>压力(如:重试次数,重试间隔,错误容忍数等),降低该问题出现频率。</p></li><li><p>如何删除全部的顶点和边,RESTful API中没有这样的接口,调用<code>gremlin</code><code>g.V().drop()</code>会报错<code>Vertices in transaction have reached capacity xxx</code></p><p>目前确实没有好办法删除全部的数据,用户如果是自己部署的<code>Server</code>和后端,可以直接清空数据库,重启<code>Server</code>。可以使用paging API或scan API先获取所有数据,再逐条删除。</p></li><li><p>清空了数据库,并且执行了<code>init-store</code>,但是添加<code>schema</code>时提示"xxx has existed"</p><p><code>HugeGraphServer</code>内是有缓存的,清空数据库的同时是需要重启<code>Server</code>的,否则残留的缓存会产生不一致。</p></li><li><p>插入顶点或边的过程中报错:<code>Id max length is 128, but got xxx {yyy}</code><code>Big id max length is 32768, but got xxx</code></p><p>为了保证查询性能,目前的后端存储对id列的长度做了限制,顶点id不能超过128字节,边id长度不能超过32768字节,索引id不能超过128字节。</p></li><li><p>是否支持嵌套属性,如果不支持,是否有什么替代方案</p><p>嵌套属性目前暂不支持。替代方案:可以把嵌套属性作为单独的顶点拿出来,然后用边连接起来。</p></li><li><p>一个<code>EdgeLabel</code>是否可以连接多对<code>VertexLabel</code>,比如"投资"关系,可以是"个人"投资"企业",也可以是"企业"投资"企业"</p><p>一个<code>EdgeLabel</code>不支持连接多对<code>VertexLabel</code>,需要用户将<code>EdgeLabel</code>拆分得更细一点,如:&ldquo;个人投资&rdquo;,&ldquo;企业投资&rdquo;。</p></li><li><p>通过<code>RestAPI</code>发送请求时提示<code>HTTP 415 Unsupported Media Type</code></p><p>请求头中需要指定<code>Content-Type:application/json</code></p></li></ul><p>其他问题可以在对应项目的 issue 区搜索,例如 <a href=https://github.com/apache/hugegraph/issues>Server-Issues</a> / <a href=https://github.com/apache/hugegraph-toolchain/issues>Loader Issues</a></p></div><div class=td-content style=page-break-before:always><h1 id=pg-d54c862d45861ca39a945d90325e3909>6 - 报告安全问题</h1><h2 id=报告-apache-hugegraph-的安全问题>报告 Apache HugeGraph 的安全问题</h2><p>遵循 ASF 的规范,HugeGraph 社区对<strong>解决修复</strong>项目中的安全问题保持非常积极和开放的态度。</p><p>我们强烈建议用户首先向我们的独立安全邮件列表报告此类问题,相关详细的流程规范请参考 <a href=https://www.apache.org/security/committers.html>ASF SEC</a> 守则。</p><p>请注意,安全邮件组适用于报告<strong>未公开</strong>的安全漏洞并跟进漏洞处理的过程。常规的软件 <code>Bug/Error</code> 报告应该使用 <code>Github Issue/Discussion</code>
或是 <code>HugeGraph-Dev</code> 邮箱组。发送到安全邮件组但与安全问题无关的邮件将被忽略。</p><p>独立的安全邮件 (组) 地址为: <code>security@hugegraph.apache.org</code></p><p>安全漏洞处理大体流程如下:</p><ul><li>报告人私下向 Apache HugeGraph SEC 邮件组报告漏洞 (尽可能包括复现的版本/相关说明/复现方式/影响范围等)</li><li>HugeGraph 项目安全团队与报告人私下合作/商讨漏洞解决方案 (初步确认后可申请 <code>CVE</code> 编号予以登记)</li><li>项目创建一个新版本的受漏洞影响的软件包,以提供修复程序</li><li>合适的时间可公开漏洞的大体问题 & 描述如何应用修复程序 (遵循 ASF 规范,公告中不应携带复现细节等敏感信息)</li><li>正式的 CVE 发布及相关流程同 ASF-SEC 页面</li></ul><h2 id=已发现的安全漏洞-cves>已发现的安全漏洞 (CVEs)</h2><h3 id=hugegraphhttpsgithubcomapachehugegraph-主仓库-serverpdstore><a href=https://github.com/apache/hugegraph>HugeGraph</a> 主仓库 (Server/PD/Store)</h3><ul><li><a href="https://www.cve.org/CVERecord?id=CVE-2024-27348">CVE-2024-27348</a>: HugeGraph-Server - Command execution in gremlin</li><li><a href="https://www.cve.org/CVERecord?id=CVE-2024-27349">CVE-2024-27349</a>: HugeGraph-Server - Bypass whitelist in Auth mode</li></ul><h3 id=hugegraph-toolchainhttpsgithubcomapachehugegraph-toolchain-仓库-hubbleloaderclienttools><a href=https://github.com/apache/hugegraph-toolchain>HugeGraph-Toolchain</a> 仓库 (Hubble/Loader/Client/Tools/..)</h3><ul><li><a href="https://www.cve.org/CVERecord?id=CVE-2024-27347">CVE-2024-27347</a>: HugeGraph-Hubble - SSRF in Hubble connection page</li></ul></div></main></div></div><footer class="bg-dark py-3 row d-print-none"><div class=footer-container><div class="row bg-dark"><div class=col-1></div><div class="col-4 text-center container-center"><div class=footer-row><a href=https://www.apache.org><div class=footer-apache-logo><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 7127.6 2890" enable-background="new 0 0 7127.6 2890"><path fill="#6d6e71" d="M7104.7 847.8c15.3 15.3 22.9 33.7 22.9 55.2s-7.6 39.9-22.9 55.4c-15.3 15.4-33.8 23.1-55.6 23.1s-40.2-7.6-55.4-22.9c-15.1-15.3-22.7-33.7-22.7-55.2s7.6-39.9 22.9-55.4c15.3-15.4 33.7-23.1 55.4-23.1C7070.9 824.9 7089.4 832.5 7104.7 847.8zM7098.1 951.9c13.3-13.6 20-29.8 20-48.7s-6.6-35-19.8-48.5c-13.2-13.4-29.4-20.1-48.6-20.1-19.2.0-35.4 6.7-48.7 20.2s-19.9 29.7-19.9 48.7 6.6 35.2 19.7 48.6c13.1 13.4 29.3 20.1 48.5 20.1S7084.7 965.4 7098.1 951.9zm-11-63.8c0 14-6.1 22.8-18.4 26.4l22.5 30.5H7073l-20.3-28.3h-18.6V945h-14.7v-84.6h31.8c12.8.0 22 2.2 27.6 6.6C7084.4 871.4 7087.1 878.4 7087.1 888.1zM7068.2 9e2c3-2.4 4.4-6.5 4.4-12s-1.5-9.4-4.5-11.6-8.4-3.2-16-3.2h-18v30.5h17.5C7059.7 903.6 7065.3 902.4 7068.2 9e2z"/><path fill="#6d6e71" d="M1803.6 499.8v155.4h-20V499.8h-56.8v-19.2h133.9v19.2H1803.6z"/><path fill="#6d6e71" d="M2082.2 655.2v-76.9H1977v76.9h-20V480.5h20v78.9h105.2v-78.9h20v174.7h-20z"/><path fill="#6d6e71" d="M2241.4 499.8v57.4h88.1v19.2h-88.1v59.8h101.8v19h-121.8V480.5H2340v19.2H2241.4z"/><path fill="#d22128" d="M1574.5 1852.4l417.3-997.6h80.1l417.3 997.6h-105.4l-129.3-311.9h-448.2l-127.9 311.9H1574.5zM2032.6 970l-205.1 493.2h404.7L2032.6 970z"/><path fill="#d22128" d="M2596.9 1852.4V854.8H3010c171.4.0 295.1 158.8 295.1 313.3.0 163-115.2 316.1-286.6 316.1h-324.6v368.1h-97zm97-455.3h318.9c118 0 193.9-108.2 193.9-229 0-125.1-92.7-226.2-202.3-226.2h-310.5v455.2z"/><path fill="#d22128" d="M3250.5 1852.4l417.3-997.6h80.1l417.3 997.6h-105.4l-129.3-311.9h-448.2l-127.9 311.9H3250.5zM3708.6 970l-205.1 493.2h404.7L3708.6 970z"/><path fill="#d22128" d="M4637.3 849.1c177 0 306.3 89.9 368.1 217.8l-78.7 47.8c-63.2-132.1-186.9-177-295.1-177-238.9.0-369.5 213.6-369.5 414.5.0 220.6 161.6 420.1 373.7 420.1 112.4.0 244.5-56.2 307.7-185.5l81.5 42.1c-64.6 148.9-241.7 231.8-394.8 231.8-274 0-466.5-261.3-466.5-514.2C4163.8 1106.3 4336.6 849.1 4637.3 849.1z"/><path fill="#d22128" d="M5949.1 854.8v997.6h-98.4v-466.5h-591.5v466.5h-96.9V854.8h96.9v444h591.5v-444H5949.1z"/><path fill="#d22128" d="M6844.6 1765.2v87.1h-670.2V854.8H6832v87.1h-560.6v359.7h489v82.9h-489v380.8H6844.6z"/><path fill="#6d6e71" d="M1667.6 2063.6c11.8 3.5 22.2 8.3 31 14.2l-10.3 22.6c-9-6-18.6-10.4-28.9-13.4-10.2-2.9-20-4.4-29.2-4.4-13.6.0-24.5 2.4-32.6 7.3s-12.2 11.8-12.2 20.7c0 7.6 2.3 14 6.8 19s10.2 8.9 17 11.7c6.8 2.8 16.1 6 28 9.6 14.4 4.6 26 8.9 34.7 12.9 8.8 4 16.3 9.9 22.5 17.8 6.2 7.8 9.3 18.2 9.3 31 0 11.7-3.2 21.8-9.5 30.6-6.3 8.7-15.3 15.5-26.8 20.3-11.6 4.8-24.9 7.2-40 7.2s-29.7-2.9-43.9-8.7c-14.2-5.8-26.4-13.6-36.6-23.4l10.7-21.6c9.6 9.4 20.7 16.7 33.3 21.9 12.6 5.2 24.8 7.8 36.8 7.8 15.3.0 27.3-3 36.1-8.9s13.2-13.9 13.2-23.9c0-7.8-2.3-14.3-6.9-19.4-4.6-5.1-10.3-9-17.1-11.9-6.8-2.8-16.1-6-28-9.6-14.2-4.2-25.7-8.3-34.6-12.2-8.9-3.9-16.4-9.7-22.5-17.5-6.1-7.7-9.2-17.9-9.2-30.6.0-10.9 3-20.4 9-28.6s14.6-14.6 25.6-19.1c11.1-4.5 23.8-6.8 38.2-6.8C1643.8 2058.3 1655.7 2060.1 1667.6 2063.6z"/><path fill="#6d6e71" d="M1980.1 2072.8c16.8 9.4 30.2 22.3 40 38.4 9.8 16.2 14.8 33.9 14.8 53.3.0 19.5-4.9 37.4-14.8 53.6-9.8 16.3-23.2 29.1-40 38.6s-35.3 14.3-55.2 14.3c-20.3.0-38.8-4.7-55.7-14.3-16.8-9.5-30.2-22.4-40-38.6-9.8-16.3-14.8-34.1-14.8-53.6s4.9-37.3 14.8-53.5c9.8-16.2 23.2-29 40-38.3 16.8-9.4 35.4-14 55.7-14C1944.8 2058.6 1963.2 2063.3 1980.1 2072.8zM1881.9 2092.7c-13.1 7.4-23.6 17.5-31.4 30.1-7.8 12.6-11.8 26.5-11.8 41.7.0 15.3 3.9 29.3 11.8 42 7.8 12.7 18.3 22.8 31.4 30.2 13.1 7.4 27.4 11.1 42.9 11.1s29.7-3.7 42.7-11.1 23.3-17.4 31.1-30.2c7.7-12.7 11.6-26.7 11.6-42s-3.9-29.2-11.6-41.8c-7.7-12.6-18.1-22.6-31.1-30s-27.2-11.2-42.6-11.2C1909.4 2081.5 1895.1 2085.2 1881.9 2092.7z"/><path fill="#6d6e71" d="M2186.5 2082.4v74h98.4v23.2h-98.4v90.2h-24.1v-210.6h133.8v23.2H2186.5z"/><path fill="#6d6e71" d="M2491.6 2082.4v187.4h-24.1v-187.4h-68.4v-23.2h161.4v23.2H2491.6z"/><path fill="#6d6e71" d="M2871.8 2269.8l-56.8-177.4-57.6 177.4h-24.5l-70.5-210.6h25.9l57.9 182.7 57.1-182.4 24.1-.3 57.7 182.7 57.1-182.7h25l-70.6 210.6H2871.8z"/><path fill="#6d6e71" d="M3087.3 2216.6l-23.5 53.2h-25.6l94.4-210.6h25l94.1 210.6h-26.1l-23.5-53.2H3087.3zM3144.5 2086.6l-46.9 106.8h94.4l-47.5-106.8z"/><path fill="#6d6e71" d="M3461.1 2202.7c-6 .4-10.7.6-14.1.6h-56v66.5h-24v-210.6h80c26.2.0 46.6 6.2 61.2 18.5 14.5 12.3 21.8 29.8 21.8 52.3.0 17.2-4.1 31.7-12.2 43.3-8.1 11.6-19.8 20-35 25l49.2 71.5h-27.3L3461.1 2202.7zM3491.3 2167.6c10.3-8.4 15.5-20.8 15.5-37 0-15.9-5.2-27.9-15.5-36s-25.1-12.2-44.3-12.2h-56v97.8h56C3466.2 2180.2 3481 2176 3491.3 2167.6z"/><path fill="#6d6e71" d="M3688.3 2082.4v69.2h106.2v23.2h-106.2v72.1h122.8v22.9h-146.9v-210.6h142.9v23.2H3688.3z"/><path fill="#6d6e71" d="M4147 2082.4v74h98.4v23.2H4147v90.2h-24.1v-210.6h133.8v23.2H4147z"/><path fill="#6d6e71" d="M4523.3 2072.8c16.8 9.4 30.2 22.3 40 38.4 9.8 16.2 14.8 33.9 14.8 53.3.0 19.5-4.9 37.4-14.8 53.6-9.8 16.3-23.2 29.1-40 38.6s-35.3 14.3-55.2 14.3c-20.3.0-38.8-4.7-55.7-14.3-16.8-9.5-30.2-22.4-40-38.6-9.8-16.3-14.8-34.1-14.8-53.6s4.9-37.3 14.8-53.5c9.8-16.2 23.2-29 40-38.3 16.8-9.4 35.4-14 55.7-14C4488.1 2058.6 4506.5 2063.3 4523.3 2072.8zM4425.2 2092.7c-13.1 7.4-23.6 17.5-31.4 30.1-7.8 12.6-11.8 26.5-11.8 41.7.0 15.3 3.9 29.3 11.8 42 7.8 12.7 18.3 22.8 31.4 30.2 13.1 7.4 27.4 11.1 42.9 11.1s29.7-3.7 42.7-11.1 23.3-17.4 31.1-30.2c7.7-12.7 11.6-26.7 11.6-42s-3.9-29.2-11.6-41.8c-7.7-12.6-18.1-22.6-31.1-30s-27.2-11.2-42.6-11.2C4452.6 2081.5 4438.3 2085.2 4425.2 2092.7z"/><path fill="#6d6e71" d="M4854.7 2247.7c-15.7 15.5-37.3 23.3-64.8 23.3-27.7.0-49.4-7.8-65.1-23.3-15.7-15.5-23.6-37-23.6-64.6v-124h24.1v124c0 20.3 5.8 36.1 17.3 47.5 11.6 11.4 27.3 17.1 47.3 17.1 20.1.0 35.8-5.7 47.1-17 11.4-11.3 17-27.2 17-47.7v-124h24.1v124C4878.2 2210.7 4870.4 2232.2 4854.7 2247.7z"/><path fill="#6d6e71" d="M5169.5 2269.8l-126.3-169.1v169.1h-24.1v-210.6h25l126.3 169.3v-169.3h23.8v210.6H5169.5z"/><path fill="#6d6e71" d="M5478.4 2073.1c16.4 9.3 29.4 21.9 38.9 37.9 9.6 16 14.3 33.9 14.3 53.5s-4.8 37.6-14.3 53.6c-9.5 16.1-22.6 28.7-39.3 37.9-16.6 9.2-35.2 13.8-55.5 13.8h-84.3v-210.6h85.2C5443.7 2059.2 5462 2063.8 5478.4 2073.1zM5362.3 2246.9h61.4c15.5.0 29.6-3.5 42.3-10.6s22.8-16.9 30.2-29.5c7.4-12.5 11.1-26.5 11.1-42s-3.8-29.4-11.3-41.9-17.7-22.3-30.6-29.6c-12.8-7.2-27-10.9-42.6-10.9h-60.5v164.5z"/><path fill="#6d6e71" d="M5668.6 2216.6l-23.5 53.2h-25.6l94.4-210.6h25l94.1 210.6h-26l-23.5-53.2H5668.6zM5725.8 2086.6l-46.9 106.8h94.4l-47.5-106.8z"/><path fill="#6d6e71" d="M5991 2082.4v187.4h-24v-187.4h-68.4v-23.2H6060v23.2h-69z"/><path fill="#6d6e71" d="M6175.9 2269.8v-210.6h24.1v210.6H6175.9z"/><path fill="#6d6e71" d="M6493.7 2072.8c16.8 9.4 30.2 22.3 40 38.4 9.8 16.2 14.8 33.9 14.8 53.3.0 19.5-4.9 37.4-14.8 53.6-9.8 16.3-23.2 29.1-40 38.6s-35.3 14.3-55.2 14.3c-20.3.0-38.8-4.7-55.7-14.3-16.8-9.5-30.2-22.4-40-38.6-9.8-16.3-14.8-34.1-14.8-53.6s4.9-37.3 14.8-53.5c9.8-16.2 23.2-29 40-38.3 16.8-9.4 35.4-14 55.7-14C6458.5 2058.6 6476.9 2063.3 6493.7 2072.8zM6395.6 2092.7c-13.1 7.4-23.6 17.5-31.4 30.1-7.8 12.6-11.8 26.5-11.8 41.7.0 15.3 3.9 29.3 11.8 42 7.8 12.7 18.3 22.8 31.4 30.2 13.1 7.4 27.4 11.1 42.9 11.1s29.7-3.7 42.7-11.1 23.3-17.4 31.1-30.2c7.7-12.7 11.6-26.7 11.6-42s-3.9-29.2-11.6-41.8c-7.7-12.6-18.1-22.6-31.1-30s-27.2-11.2-42.6-11.2C6423 2081.5 6408.8 2085.2 6395.6 2092.7z"/><path fill="#6d6e71" d="M6826.5 2269.8l-126.3-169.1v169.1h-24.1v-210.6h25l126.3 169.3v-169.3h23.8v210.6H6826.5z"/><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-4516.6152" y1="-2338.7222" x2="-4108.4111" y2="-1861.3982" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset="0" style="stop-color:#F69923"/><stop offset=".3123" style="stop-color:#F79A23"/><stop offset=".8383" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_1_)" d="M1230.1 13.7c-45.3 26.8-120.6 102.5-210.5 212.3l82.6 155.9c58-82.9 116.9-157.5 176.3-221.2 4.6-5.1 7-7.5 7-7.5-2.3 2.5-4.6 5-7 7.5-19.2 21.2-77.5 89.2-165.5 224.4 84.7-4.2 214.9-21.6 321.1-39.7 31.6-177-31-258-31-258S1323.4-41.4 1230.1 13.7z"/><path fill="none" d="M1090.2 903.1c.6-.1 1.2-.2 1.8-.3l-11.9 1.3c-.7.3-1.4.7-2.1 1C1082.1 904.4 1086.2 903.7 1090.2 903.1z"/><path fill="none" d="M1005.9 1182.3c-6.7 1.5-13.7 2.7-20.7 3.7C992.3 1185 999.2 1183.8 1005.9 1182.3z"/><path fill="none" d="M432.9 1808.8c.9-2.3 1.8-4.7 2.6-7 18.2-48 36.2-94.7 54-140.1 20-51 39.8-100.4 59.3-148.3 20.6-50.4 40.9-99.2 60.9-146.3 21-49.4 41.7-97 62-142.8 16.5-37.3 32.8-73.4 48.9-108.3 5.4-11.7 10.7-23.2 16-34.6 10.5-22.7 21-44.8 31.3-66.5 9.5-20 19-39.6 28.3-58.8 3.1-6.4 6.2-12.8 9.3-19.1.5-1 1-2 1.5-3.1l-10.2 1.1-8-15.9c-.8 1.6-1.6 3.1-2.4 4.6-14.5 28.8-28.9 57.9-43.1 87.2-8.2 16.9-16.4 34-24.6 51-22.6 47.4-44.8 95.2-66.6 143.3-22.1 48.6-43.7 97.5-64.9 146.5-20.8 48.1-41.3 96.2-61.2 144.2-20 48-39.5 95.7-58.5 143.2-19.9 49.5-39.2 98.7-58 147.2-4.2 10.9-8.5 21.9-12.7 32.8-15 39.2-29.7 77.8-44 116l12.7 25.1 11.4-1.2c.4-1.1.8-2.3 1.3-3.4C396.7 1905.4 414.9 1856.4 432.9 1808.8z"/><path fill="none" d="M980 1186.8c.1.0.1.0.1-.1C980.1 1186.8 980.1 1186.8 980 1186.8z"/><path fill="#be202e" d="M952.6 1323c-10.6 1.9-21.4 3.8-32.5 5.7-.1.0-.1.1-.2.1 5.6-.8 11.2-1.7 16.6-2.6C942 1325.2 947.3 1324.1 952.6 1323z"/><path opacity=".35" fill="#be202e" d="M952.6 1323c-10.6 1.9-21.4 3.8-32.5 5.7-.1.0-.1.1-.2.1 5.6-.8 11.2-1.7 16.6-2.6C942 1325.2 947.3 1324.1 952.6 1323z"/><path fill="#be202e" d="M980.3 1186.7C980.2 1186.7 980.2 1186.7 980.3 1186.7c-.1.1-.2.1-.2.1 1.8-.2 3.5-.5 5.2-.8 7-1 13.9-2.2 20.7-3.7C997.5 1183.8 989 1185.2 980.3 1186.7z"/><path opacity=".35" fill="#be202e" d="M980.3 1186.7C980.2 1186.7 980.2 1186.7 980.3 1186.7c-.1.1-.2.1-.2.1 1.8-.2 3.5-.5 5.2-.8 7-1 13.9-2.2 20.7-3.7C997.5 1183.8 989 1185.2 980.3 1186.7z"/><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-7537.7339" y1="-2391.4075" x2="-4625.4141" y2="-2391.4075" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_2_)" d="M858.6 784.7c25.1-46.9 50.5-92.8 76.2-137.4 26.7-46.4 53.7-91.3 80.9-134.7 1.6-2.6 3.2-5.2 4.8-7.7 27-42.7 54.2-83.7 81.6-122.9L1019.5 226c-6.2 7.6-12.5 15.3-18.8 23.2-23.8 29.7-48.6 61.6-73.9 95.5-28.6 38.2-58 78.9-87.8 121.7-27.6 39.5-55.5 80.9-83.5 123.7-23.8 36.5-47.7 74-71.4 112.5-.9 1.4-1.8 2.9-2.6 4.3L789 919.2c22.8-45.6 46.1-90.5 69.6-134.5z"/><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-7186.1777" y1="-2099.3059" x2="-5450.7183" y2="-2099.3059" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset="0" style="stop-color:#282662"/><stop offset=".0954839" style="stop-color:#662E8D"/><stop offset=".7882" style="stop-color:#9F2064"/><stop offset=".9487" style="stop-color:#CD2032"/></linearGradient><path fill="url(#SVGID_3_)" d="M369 1981c-14.2 39.1-28.5 78.9-42.9 119.6-.2.6-.4 1.2-.6 1.8-2 5.7-4.1 11.5-6.1 17.2-9.7 27.4-18 52.1-37.3 108.2 31.7 14.5 57.1 52.5 81.1 95.6-2.6-44.7-21-86.6-56.2-119.1 156.1 7 290.6-32.4 360.1-146.6 6.2-10.2 11.9-20.9 17-32.2-31.6 40.1-70.8 57.1-144.5 53-.2.1-.3.1-.5.2.2-.1.3-.1.5-.2 108.6-48.6 163.1-95.3 211.2-172.6 11.4-18.3 22.5-38.4 33.8-60.6-94.9 97.5-205 125.3-320.9 104.2l-86.9 9.5C374.4 1966.3 371.7 1973.6 369 1981z"/><linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-7374.1626" y1="-2418.5454" x2="-4461.8428" y2="-2418.5454" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_4_)" d="M409.6 1786.3c18.8-48.5 38.1-97.7 58-147.2 19-47.4 38.5-95.2 58.5-143.2s40.4-96.1 61.2-144.2c21.2-49 42.9-97.8 64.9-146.5 21.8-48.1 44-95.9 66.6-143.3 8.1-17.1 16.3-34.1 24.6-51 14.2-29.3 28.6-58.4 43.1-87.2.8-1.6 1.6-3.1 2.4-4.6L681.4 706.8c-1.8 2.9-3.5 5.8-5.3 8.6-25.1 40.9-50 82.7-74.4 125.4-24.7 43.1-49 87.1-72.7 131.7-20 37.6-39.6 75.6-58.6 113.9-3.8 7.8-7.6 15.5-11.3 23.2-23.4 48.2-44.6 94.8-63.7 139.5-21.7 50.7-40.7 99.2-57.5 145.1-11 30.2-21 59.4-30.1 87.4-7.5 24-14.7 47.9-21.5 71.8-16 56.3-29.9 112.4-41.2 168.3L353 1935.1c14.3-38.1 28.9-76.8 44-116C401.1 1808.2 405.4 1797.3 409.6 1786.3z"/><linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-7161.7642" y1="-2379.1431" x2="-5631.2524" y2="-2379.1431" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset="0" style="stop-color:#282662"/><stop offset=".0954839" style="stop-color:#662E8D"/><stop offset=".7882" style="stop-color:#9F2064"/><stop offset=".9487" style="stop-color:#CD2032"/></linearGradient><path fill="url(#SVGID_5_)" d="M243.5 1729.4c-13.6 68.2-23.2 136.2-28 203.8-.2 2.4-.4 4.7-.5 7.1-33.7-54-124-106.8-123.8-106.2 64.6 93.7 113.7 186.7 120.9 278-34.6 7.1-82-3.2-136.8-23.3 57.1 52.5 1e2 67 116.7 70.9-52.5 3.3-107.1 39.3-162.1 80.8 80.5-32.8 145.5-45.8 192.1-35.3C148.1 2414.2 74.1 2645 0 2890c22.7-6.7 36.2-21.9 43.9-42.6 13.2-44.4 100.8-335.6 238-718.2 3.9-10.9 7.8-21.8 11.8-32.9 1.1-3 2.2-6.1 3.3-9.2 14.5-40.1 29.5-81.1 45.1-122.9 3.5-9.5 7.1-19 10.7-28.6.1-.2.1-.4.2-.6l-107.9-213.2C244.6 1724.4 244 1726.9 243.5 1729.4z"/><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-7374.1626" y1="-2117.1309" x2="-4461.8428" y2="-2117.1309" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_6_)" d="M805.6 937c-3.1 6.3-6.2 12.7-9.3 19.1-9.3 19.2-18.8 38.8-28.3 58.8-10.3 21.7-20.7 43.9-31.3 66.5-5.3 11.4-10.6 22.9-16 34.6-16.1 35-32.4 71.1-48.9 108.3-20.3 45.8-41 93.4-62 142.8-20 47.1-40.3 95.9-60.9 146.3-19.5 47.9-39.3 97.3-59.3 148.3-17.8 45.4-35.9 92.1-54 140.1-.9 2.3-1.8 4.7-2.6 7-18 47.6-36.2 96.6-54.6 146.8-.4 1.1-.8 2.3-1.3 3.4l86.9-9.5c-1.7-.3-3.5-.5-5.2-.9 103.9-13 242.1-90.6 331.4-186.5 41.1-44.2 78.5-96.3 113-157.3 25.7-45.4 49.8-95.8 72.8-151.5 20.1-48.7 39.4-101.4 58-158.6-23.9 12.6-51.2 21.8-81.4 28.2-5.3 1.1-10.7 2.2-16.1 3.1-5.5 1-11 1.8-16.6 2.6.1.0.1-.1.2-.1 96.9-37.3 158-109.2 202.4-197.4-25.5 17.4-66.9 40.1-116.6 51.1-6.7 1.5-13.7 2.7-20.7 3.7-1.7.3-3.5.6-5.2.8.1.0.1.0.1-.1h.1c33.6-14.1 62-29.8 86.6-48.4 5.3-4 10.4-8.1 15.3-12.3 7.5-6.5 14.7-13.3 21.5-20.5 4.4-4.6 8.6-9.3 12.7-14.2 9.6-11.5 18.7-23.9 27.1-37.3 2.6-4.1 5.1-8.3 7.6-12.6 3.2-6.2 6.3-12.3 9.3-18.3 13.5-27.2 24.4-51.5 33-72.8 4.3-10.6 8.1-20.5 11.3-29.7 1.3-3.7 2.5-7.2 3.7-10.6 3.4-10.2 6.2-19.3 8.4-27.3 3.3-12 5.3-21.5 6.4-28.4-3.3 2.6-7.1 5.2-11.3 7.7-29.3 17.5-79.5 33.4-119.9 40.8l79.8-8.8-79.8 8.8c-.6.1-1.2.2-1.8.3-4 .7-8.1 1.3-12.2 2 .7-.3 1.4-.7 2.1-1l-273 29.9C806.6 935 806.1 936 805.6 937z"/><linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-7554.8232" y1="-2132.0981" x2="-4642.5034" y2="-2132.0981" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_7_)" d="M1112.9 385.1c-24.3 37.3-50.8 79.6-79.4 127.5-1.5 2.5-3 5.1-4.5 7.6-24.6 41.5-50.8 87.1-78.3 137-23.8 43.1-48.5 89.3-74.3 139C854 839.5 830.8 885.4 807 934l273-29.9c79.5-36.6 115.1-69.7 149.6-117.6 9.2-13.2 18.4-27 27.5-41.3 28-43.8 55.6-92 80.1-139.9 23.7-46.3 44.7-92.2 60.7-133.5 10.2-26.3 18.4-50.8 24.1-72.3 5-19 8.9-36.9 11.9-54.1C1327.9 363.5 1197.6 380.9 1112.9 385.1z"/><path fill="#be202e" d="M936.5 1326.1c-5.5 1-11 1.8-16.6 2.6C925.5 1328 931 1327.1 936.5 1326.1z"/><path opacity=".35" fill="#be202e" d="M936.5 1326.1c-5.5 1-11 1.8-16.6 2.6C925.5 1328 931 1327.1 936.5 1326.1z"/><linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-7374.1626" y1="-2027.484" x2="-4461.8433" y2="-2027.484" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_8_)" d="M936.5 1326.1c-5.5 1-11 1.8-16.6 2.6C925.5 1328 931 1327.1 936.5 1326.1z"/><path fill="#be202e" d="M980 1186.8c1.8-.2 3.5-.5 5.2-.8C983.5 1186.3 981.8 1186.6 980 1186.8z"/><path opacity=".35" fill="#be202e" d="M980 1186.8c1.8-.2 3.5-.5 5.2-.8C983.5 1186.3 981.8 1186.6 980 1186.8z"/><linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="-7374.1626" y1="-2037.7417" x2="-4461.8433" y2="-2037.7417" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_9_)" d="M980 1186.8c1.8-.2 3.5-.5 5.2-.8C983.5 1186.3 981.8 1186.6 980 1186.8z"/><path fill="#be202e" d="M980.2 1186.7z"/><path opacity=".35" fill="#be202e" d="M980.2 1186.7z"/><linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="-5738.0635" y1="-2039.799" x2="-5094.3457" y2="-2039.799" gradientTransform="matrix(0.4226 -0.9063 0.9063 0.4226 5117.8774 -2859.9343)"><stop offset=".3233" style="stop-color:#9E2064"/><stop offset=".6302" style="stop-color:#C92037"/><stop offset=".7514" style="stop-color:#CD2335"/><stop offset="1" style="stop-color:#E97826"/></linearGradient><path fill="url(#SVGID_10_)" d="M980.2 1186.7z"/></svg></div></a><ul class=footer-link><li><a class=white href=http://www.apache.org>Foundation</a></li><li><a class=white href=http://www.apache.org/licenses/>License</a></li><li><a class=white href=https://www.apache.org/security/>Security</a></li><li><a class=white href=http://www.apache.org/events/current-event>Events</a></li><li><a class=white href=http://www.apache.org/foundation/sponsorship.html>Sponsorship</a></li><li><a class=white href=http://www.apache.org/foundation/thanks.html>Thanks</a></li><li><a class=white href=https://privacy.apache.org/policies/privacy-policy-public.html target=_blank>Privacy</a></li></ul></div></div><div class="col-6 text-white text-center container-center"><p>Copyright &copy; 2024 The Apache Software Foundation, Licensed under the <a class=white href=https://www.apache.org/licenses/LICENSE-2.0>Apache License Version 2.0</a></p><p>Apache and the Apache feather logo are trademarks of The Apache Software Foundation.</p></div><div class=col-1></div></div></div></footer></div><script src=https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js integrity=sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN crossorigin=anonymous></script>
<script src=https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js integrity="sha512-UR25UO94eTnCVwjbXozyeVd6ZqpaAE9naiEUBK/A+QDbfSTQFhPGj5lOR6d8tsgbBk84Ggb5A3EkjsOgPRPcKA==" crossorigin=anonymous></script>
<script src=/js/tabpane-persist.js></script>
<script src=/js/main.min.aa9f4c5dae6a98b2c46277f4c56f1673a2b000d1756ce4ffae93784cab25e6d5.js integrity="sha256-qp9MXa5qmLLEYnf0xW8Wc6KwANF1bOT/rpN4TKsl5tU=" crossorigin=anonymous></script>
<script src=/js/prism.js></script></body></html>