# How ResourceManagerPersistence Handles Engine Resource Allocation in Apache Linkis: A Deep Dive into ResourceLabel Entities

> Discover how ResourceManagerPersistence in Apache Linkis manages engine resource allocation using ResourceLabel entities for efficient discovery and locking via relational database persistence.

- Repository: [The Apache Software Foundation/linkis](https://github.com/apache/linkis)
- Tags: deep-dive
- Published: 2026-02-25

---

**ResourceManagerPersistence in Apache Linkis manages engine resource allocation by persisting `PersistenceResource` objects to a relational database and binding them to metadata through `ResourceLabel` entities (`PersistenceLabel` and `PersistenceLabelRel`), enabling label-based resource discovery and exclusive locking.**

Apache Linkis orchestrates distributed computation engines across heterogeneous clusters using a sophisticated resource management system. The **ResourceManagerPersistence** layer provides the durable storage foundation for engine resource allocation, mapping CPU, memory, and GPU metrics to specific engine instances through the `ResourceLabel` entity system. This persistence layer, implemented primarily in `DefaultResourceManagerPersistence`, bridges the gap between transient engine processes and permanent resource records using MyBatis mappers.

## The ResourceManagerPersistence Architecture

The **ResourceManagerPersistence** interface defines the contract for resource storage operations, while `DefaultResourceManagerPersistence` provides the concrete implementation. This class acts as a thin DAO façade that delegates SQL execution to MyBatis mappers including `ResourceManagerMapper`, `LabelManagerMapper`, and `NodeManagerMapper`.

The persistence layer stores three core entity types: `PersistenceResource` (holding actual resource metrics), `PersistenceLabel` (containing metadata labels), and `PersistenceLabelRel` (managing many-to-many relationships between resources and labels).

## Engine Resource Allocation Lifecycle

Linkis manages engine resources through a complete lifecycle from registration to cleanup. Each phase involves specific persistence operations that maintain consistency between active engines and database records.

### Resource Registration and Label Binding

When an engine or EngineManager (EM) starts, it registers its available resources through `ResourceManagerPersistence.registerResource(...)`. In `DefaultResourceManagerPersistence` ([source L71‑L77](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L71-L77)), this method inserts a `PersistenceResource` row containing the instance identifier, resource type, ticket ID, and serialized resource metrics.

Immediately after resource insertion, the implementation establishes label associations. It fetches label IDs belonging to the engine instance via `labelManagerMapper.getLabelIdsByInstance`, then creates the mapping through `labelManagerMapper.addLabelsAndResource` ([source L88‑L93](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L88-L93)). This two-phase commit ensures every resource record links to its descriptive metadata.

### Updating Engine Allocations

Dynamic resource scaling triggers updates through `nodeResourceUpdate`. The implementation first retrieves the existing resource ID using the ticket identifier (`getNodeResourceUpdateResourceId`), then updates the `PersistenceResource` row with new CPU, memory, or GPU values ([source L61‑L68](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L61-L68)). This pattern ensures atomic updates without creating duplicate resource records.

### Exclusive Resource Locking

For scenarios requiring dedicated resource allocation, `lockResource` provides atomic registration and label binding. This method combines resource insertion with immediate label relation creation in a single logical operation ([source L92‑L97](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L92-L97)). By executing both steps together, the persistence layer guarantees that a resource is "locked" to a specific label set, preventing concurrent allocation attempts from other schedulers.

### Label-Based Resource Discovery

Clients such as the Linkis Scheduler and Resource Pool discover engines through label queries. The `getResourceByLabel` method delegates to `labelManagerMapper` to execute SQL joins between the label table and resource table ([source L95‑L103](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L95-L103)). This enables queries like "find all Spark engines with 8GB memory" by matching label key-value pairs against persisted resource records.

### Resource Cleanup

When engine instances terminate, `deleteServiceInstanceResource` removes both the resource rows and their label relations ([source L44‑L51](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java#L44-L51)). For ticket-based temporary resources, `deleteExpiredTicketIdResource` purges records that have exceeded their session timeout, preventing database bloat from orphaned engine sessions.

## Understanding ResourceLabel Entities

The **ResourceLabel** system provides the metadata layer that makes engine resources discoverable and categorizable. Three entities cooperate to implement this labeling mechanism.

### PersistenceLabel

`PersistenceLabel` represents concrete metadata tags such as `engineType=Spark`, `resourcePool=default`, or `tenant=production`. Defined in ([source L25‑L35, L86‑L94](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabel.java#L25-L35)), this entity extends `GenericLabel` to reuse label key/value handling logic. Key fields include:

- `labelKey` and `value` (inherited from GenericLabel)
- `stringValue` (serialized representation)
- `labelValueSize` (cardinality for optimization)
- `createTime` and `updateTime` (temporal tracking)

### PersistenceLabelRel

`PersistenceLabelRel` serves as the junction table entity that implements the many-to-many relationship between resources and labels. This entity extends `PersistenceLabel` by adding a `resourceId` field that acts as a foreign key to `PersistenceResource.id` ([source L20‑L30](https://github.com/apache/linkis/blob/master/linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabelRel.java#L20-L30)). When persisted, these records populate the `persistence_label_rel` database table.

### PersistenceResource

While not detailed in the entity excerpt, `PersistenceResource` stores the actual quantitative metrics (CPU cores, memory bytes, GPU devices) alongside a `ticketId` that uniquely identifies the engine session. The resource type field distinguishes between Spark, Hive, Python, and other engine categories.

### The Label-Resource Mapping Mechanism

The binding process operates through three distinct steps:

1. **Label Resolution**: When registering a resource, the system queries existing labels via `labelManagerMapper.getLabelIdsByInstance` to retrieve the integer IDs corresponding to the engine's metadata tags.

2. **Relation Persistence**: The method `addLabelsAndResource(resourceId, labelIds)` inserts rows into the relation table, establishing the many-to-many link between the new resource and its descriptive labels.

3. **Discovery Joins**: Query methods like `getResourcesByLabel` execute SQL JOIN operations between `persistence_label_rel` and `persistence_resource`, allowing efficient retrieval of all engine instances matching specific label criteria.

## Practical Implementation Examples

Linkis manager services interact with the persistence layer through the `ResourceManagerPersistence` interface. Below are representative usage patterns:

```java
// Register a new engine resource with automatic label mapping
PersistenceResource resource = new PersistenceResource();
resource.setInstance("engine01:10001");
resource.setResourceType("spark");
resource.setTicketId("ticket-1234");
resource.setResourceInfo("{\"cpu\":4,\"memory\":8192}");
resourceManagerPersistence.registerResource(resource);
// Label mapping handled internally via LabelManagerMapper

```

```java
// Update resource allocation after dynamic scaling
PersistenceResource updatedResource = new PersistenceResource();
updatedResource.setCpu(8);
updatedResource.setMemory(16384);
resourceManagerPersistence.nodeResourceUpdate("ticket-1234", updatedResource);

```

```java
// Discover all engines matching a specific label
Label sparkLabel = new GenericLabel();
sparkLabel.setLabelKey("engineType");
sparkLabel.setStringValue("Spark");
List<PersistenceResource> sparkEngines =
    resourceManagerPersistence.getResourceByLabel(sparkLabel);

```

```java
// Lock resource for exclusive use with specific labels
List<Integer> exclusiveLabelIds = Arrays.asList(101, 102);
PersistenceResource lockedResource = new PersistenceResource();
// ... set resource properties
resourceManagerPersistence.lockResource(exclusiveLabelIds, lockedResource);

```

## Key Source Files in the Persistence Layer

| File | Path | Role |
|------|------|------|
| **ResourceManagerPersistence.java** | [`linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/ResourceManagerPersistence.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/ResourceManagerPersistence.java) | Interface defining contract for resource CRUD operations |
| **DefaultResourceManagerPersistence.java** | [`linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/persistence/impl/DefaultResourceManagerPersistence.java) | Concrete implementation coordinating MyBatis mappers |
| **ResourceManagerMapper.java** | [`linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/dao/ResourceManagerMapper.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-manager-persistence/src/main/java/org/apache/linkis/manager/dao/ResourceManagerMapper.java) | MyBatis mapper interface for SQL execution |
| **PersistenceLabel.java** | [`linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabel.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabel.java) | Entity definition for metadata labels |
| **PersistenceLabelRel.java** | [`linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabelRel.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-manager-common/src/main/java/org/apache/linkis/manager/common/entity/persistence/PersistenceLabelRel.java) | Entity definition for label-resource relationships |

## Summary

- **ResourceManagerPersistence** provides the durable storage layer for Linkis engine resources, implemented by `DefaultResourceManagerPersistence` using MyBatis mappers.
- Engine resources follow a complete lifecycle: registration with label binding, dynamic updates through `nodeResourceUpdate`, exclusive locking via `lockResource`, discovery through label queries, and cleanup on termination.
- **ResourceLabel entities** consist of `PersistenceLabel` (metadata definitions), `PersistenceLabelRel` (many-to-many join records), and `PersistenceResource` (actual capacity metrics).
- The label-resource mapping enables sophisticated scheduling by allowing the ResourceManager to query engines by characteristics like `engineType`, `resourcePool`, or custom tenant tags.
- All persistence operations execute through the `ResourceManagerMapper` and `LabelManagerMapper` interfaces, with SQL mappings defined in corresponding XML configuration files.

## Frequently Asked Questions

### What is the difference between PersistenceLabel and PersistenceLabelRel?

**PersistenceLabel** stores the actual metadata tag definitions (such as `engineType=Spark`), while **PersistenceLabelRel** acts as a junction table entity that links those label definitions to specific resource records via foreign keys. When an engine registers, the system creates or references `PersistenceLabel` records for its metadata, then creates `PersistenceLabelRel` entries to bind those labels to the engine's `PersistenceResource` record.

### How does ResourceManagerPersistence ensure atomic resource locking?

The `lockResource` method in `DefaultResourceManagerPersistence` combines resource registration and label relation creation into a single transactional operation. By executing both the `registerResource` database insert and the `addLabelsAndResource` mapping insert together, the implementation guarantees that a resource cannot be partially registered or claimed by multiple concurrent allocation requests.

### Where are the actual SQL mappings defined for these operations?

While the Java interfaces `ResourceManagerMapper` and `LabelManagerMapper` define the method signatures, the actual SQL statements are defined in MyBatis XML mapper files located in the resources directory (typically under `src/main/resources/mappers`). These XML files map Java method calls to specific INSERT, UPDATE, SELECT, and DELETE statements targeting tables like `persistence_resource`, `persistence_label`, and `persistence_label_rel`.

### How does label-based resource discovery work in practice?

When the Linkis Scheduler requests engines matching specific criteria, it constructs `PersistenceLabel` objects representing the desired characteristics. The `getResourceByLabel` method queries the database using a JOIN between the label table and resource table through the relation entity. This returns only `PersistenceResource` records that possess all specified labels, enabling efficient filtering of engine instances by their metadata rather than just their IDs.