Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
public interface ClusterMessagingService {
/**
* Send message matching the specifications mentioned in recipientCriteria.
*
* <p><b>PERFORMANCE WARNING:</b> When recipientCriteria uses {@link DataSource#EXTERNALVIEW}
* with wildcard or unspecified resource names, this scans <b>ALL</b> ExternalView znodes in the cluster,
* regardless of other criteria like instanceName. At scale (thousands of resources), this causes
* severe performance degradation. Use {@link DataSource#LIVEINSTANCES} when you don't need
* resource/partition filtering, or specify exact resource names when using EXTERNALVIEW.
*
* @param recipientCriteria criteria to be met, defined as {@link Criteria}
* @See Criteria
* @param message
Expand All @@ -54,6 +61,11 @@ public interface ClusterMessagingService {
* This method will return after sending the messages. <br>
* This is useful when message need to be sent and current thread need not
* wait for response since processing will be done in another thread.
*
* <p><b>PERFORMANCE WARNING:</b> See performance considerations in {@link #send(Criteria, Message)}.
* Using {@link DataSource#EXTERNALVIEW} with wildcard resources can scan all ExternalView znodes
* and cause severe performance issues at scale. Prefer {@link DataSource#LIVEINSTANCES} when possible.
*
* @see #send(Criteria, Message)
* @param recipientCriteria
* @param message
Expand All @@ -64,6 +76,10 @@ public interface ClusterMessagingService {
int send(Criteria recipientCriteria, Message message, AsyncCallback callbackOnReply, int timeOut);

/**
* <p><b>PERFORMANCE WARNING:</b> See performance considerations in {@link #send(Criteria, Message)}.
* Using {@link DataSource#EXTERNALVIEW} with wildcard resources can scan all ExternalView znodes
* and cause severe performance issues at scale. Prefer {@link DataSource#LIVEINSTANCES} when possible.
*
* @see #send(Criteria, Message, AsyncCallback, int)
* @param recipientCriteria
* @param message
Expand All @@ -85,6 +101,11 @@ int send(Criteria recipientCriteria, Message message, AsyncCallback callbackOnRe
* for response. <br>
* The current thread can use callbackOnReply instance to store application
* specific data.
*
* <p><b>PERFORMANCE WARNING:</b> See performance considerations in {@link #send(Criteria, Message)}.
* Using {@link DataSource#EXTERNALVIEW} with wildcard resources can scan all ExternalView znodes
* and cause severe performance issues at scale. Prefer {@link DataSource#LIVEINSTANCES} when possible.
*
* @see #send(Criteria, Message, AsyncCallback, int)
* @param recipientCriteria
* @param message
Expand All @@ -96,6 +117,10 @@ int sendAndWait(Criteria recipientCriteria, Message message, AsyncCallback callb
int timeOut);

/**
* <p><b>PERFORMANCE WARNING:</b> See performance considerations in {@link #send(Criteria, Message)}.
* Using {@link DataSource#EXTERNALVIEW} with wildcard resources can scan all ExternalView znodes
* and cause severe performance issues at scale. Prefer {@link DataSource#LIVEINSTANCES} when possible.
*
* @see #send(Criteria, Message, AsyncCallback, int, int)
* @param receipientCriteria
* @param message
Expand Down Expand Up @@ -143,6 +168,11 @@ int sendAndWait(Criteria receipientCriteria, Message message, AsyncCallback call
/**
* This will generate all messages to be sent given the recipientCriteria and MessageTemplate,
* the messages are not sent.
*
* <p><b>PERFORMANCE WARNING:</b> See performance considerations in {@link #send(Criteria, Message)}.
* Using {@link DataSource#EXTERNALVIEW} with wildcard resources can scan all ExternalView znodes
* and cause severe performance issues at scale. Prefer {@link DataSource#LIVEINSTANCES} when possible.
*
* @param recipientCriteria criteria to be met, defined as {@link Criteria}
* @param messageTemplate the Message on which to base the messages to send
* @return messages to be sent, grouped by the type of instance to send the message to
Expand Down
96 changes: 91 additions & 5 deletions helix-core/src/main/java/org/apache/helix/Criteria.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,78 @@
*/

/**
* Describes various properties that operations involving {@link Message} delivery will follow.
* Specifies recipient criteria for message delivery in a Helix cluster.
*
* <p>The {@link Criteria} object defines which instances should receive a message by specifying
* attributes like instance name, resource, partition, and state. The most critical configuration
* is {@link DataSource}, which determines where Helix looks up cluster state to resolve recipients.
*
* <p><b>PERFORMANCE WARNING:</b> Using {@link DataSource#EXTERNALVIEW} with wildcard or unspecified
* resource names causes Helix to scan ALL ExternalView znodes in the cluster, regardless of other
* criteria fields. At scale (thousands of resources), this causes severe performance degradation.
*
* <p><b>Quick Start - Common Patterns:</b>
* <pre>
* // Pattern 1: Send to specific live instance (most efficient)
* Criteria criteria = new Criteria();
* criteria.setInstanceName("host_1234");
* criteria.setRecipientInstanceType(InstanceType.PARTICIPANT);
* criteria.setDataSource(DataSource.LIVEINSTANCES);
* criteria.setSessionSpecific(true);
*
* // Pattern 2: Send to all replicas of a specific partition
* Criteria criteria = new Criteria();
* criteria.setInstanceName("%");
* criteria.setRecipientInstanceType(InstanceType.PARTICIPANT);
* criteria.setDataSource(DataSource.EXTERNALVIEW);
* criteria.setResource("MyDatabase"); // IMPORTANT: Specify exact resource name
* criteria.setPartition("MyDatabase_5");
* criteria.setSessionSpecific(true);
*
* // Pattern 3: Broadcast to all live instances
* Criteria criteria = new Criteria();
* criteria.setInstanceName("%");
* criteria.setRecipientInstanceType(InstanceType.PARTICIPANT);
* criteria.setDataSource(DataSource.LIVEINSTANCES);
* criteria.setSessionSpecific(true);
* </pre>
*
* <p><b>DataSource Selection Guide:</b>
* <ul>
* <li><b>LIVEINSTANCES:</b> Use when targeting live instances without resource/partition filtering.
* Fastest option - reads only LIVEINSTANCES znodes.</li>
* <li><b>EXTERNALVIEW:</b> Use when filtering by resource, partition, or replica state.
* ALWAYS specify exact resource names to avoid scanning all ExternalViews.</li>
* <li><b>INSTANCES:</b> Use when targeting all configured instances (live or not) based on
* instance configuration.</li>
* <li><b>IDEALSTATES:</b> Use when targeting based on ideal state configuration rather than
* current state. Less common.</li>
* </ul>
*
* @see ClusterMessagingService#send(Criteria, org.apache.helix.model.Message)
* @see org.apache.helix.messaging.CriteriaEvaluator
*/
public class Criteria {
/**
* Specifies the source of cluster state information for resolving message recipients.
*
* <p>The DataSource determines which ZooKeeper znodes Helix reads to match the criteria:
* <ul>
* <li><b>LIVEINSTANCES:</b> Reads /LIVEINSTANCES znodes. Contains only currently connected
* instances. Use when you don't need resource/partition information. Fastest option.</li>
* <li><b>INSTANCES:</b> Reads /INSTANCES/[instance] znodes. Contains instance configuration
* (host, port, enabled/disabled). Use for targeting based on instance config.</li>
* <li><b>EXTERNALVIEW:</b> Reads /EXTERNALVIEWS/[resource] znodes. Contains actual current
* replica placement and states (MASTER/SLAVE/OFFLINE). Use when you need resource/partition/state
* filtering. <b>WARNING:</b> Wildcard resource names scan ALL ExternalViews.</li>
* <li><b>IDEALSTATES:</b> Reads /IDEALSTATES/[resource] znodes. Contains desired replica
* placement. Similar performance to EXTERNALVIEW but less commonly used.</li>
* </ul>
*
* <p><b>Performance Impact:</b> LIVEINSTANCES is fastest as it reads minimal data. EXTERNALVIEW
* and IDEALSTATES can be slow at scale if wildcards are used in resource names, as Helix must
* read and deserialize all resource znodes to match the criteria.
*/
public enum DataSource {
IDEALSTATES,
EXTERNALVIEW,
Expand Down Expand Up @@ -80,8 +149,17 @@ public DataSource getDataSource() {
}

/**
* Set the current source of truth
* @param source ideal state or external view
* Set the current source of truth for resolving message recipients.
*
* <p><b>PERFORMANCE GUIDANCE:</b>
* <ul>
* <li>Use {@link DataSource#LIVEINSTANCES} when you only need to target live instances
* and don't require resource/partition/state filtering.</li>
* <li>If using {@link DataSource#EXTERNALVIEW}, always specify exact resource names via
* {@link #setResource(String)} to avoid scanning all ExternalView znodes.</li>
* </ul>
*
* @param source ideal state, external view, live instances, or instances
*/
public void setDataSource(DataSource source) {
_dataSource = source;
Expand Down Expand Up @@ -161,8 +239,16 @@ public String getResource() {
}

/**
* Set the destination resource name
* @param resourceName the resource name or % for all resources
* Set the destination resource name.
*
* <p><b>Note:</b> This field is only meaningful when using {@link DataSource#EXTERNALVIEW} or
* {@link DataSource#IDEALSTATES}. It is ignored for LIVEINSTANCES and INSTANCES.
*
* <p><b>PERFORMANCE:</b> When using EXTERNALVIEW, specifying an exact resource name (e.g., "MyDatabase")
* reads only that resource's ExternalView znode. Using wildcard "%" reads ALL ExternalView znodes
* in the cluster, which can cause severe performance issues at scale.
*
* @param resourceName the exact resource name, or "%" for all resources (avoid wildcard at scale)
*/
public void setResource(String resourceName) {
this.resourceName = resourceName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,51 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Evaluates {@link Criteria} against persisted Helix data to determine message recipients.
*
* <p><b>PERFORMANCE WARNING:</b> When using {@link DataSource#EXTERNALVIEW}, this evaluator
* will scan <b>all</b> ExternalView znodes in the cluster if the resource name is unspecified or uses wildcards
* (e.g., "%" or "*"). This scanning happens <b>even when targeting specific instances</b>, and is
* NOT automatically optimized based on other criteria fields (like instanceName).
*
* <p>At high ExternalView cardinality (thousands of resources), this can cause severe performance degradation.
*
* <p><b>Safer Patterns:</b>
* <ul>
* <li><b>Use {@link DataSource#LIVEINSTANCES}:</b> When you only need to target live instances
* and do not require resource/partition-level filtering. This reads only the LIVEINSTANCES
* znodes, which is typically much smaller and faster.</li>
* <li><b>Specify exact resource names:</b> If ExternalView is required, provide specific resource
* names in {@link Criteria#setResource(String)} instead of wildcards to limit the scan scope.</li>
* </ul>
*
* <p><b>Example - Targeting a specific instance:</b>
* <pre>
* // BAD: Scans all ExternalViews even though instance is specified
* Criteria criteria = new Criteria();
* criteria.setInstanceName("instance123");
* criteria.setDataSource(DataSource.EXTERNALVIEW);
* criteria.setResource("%"); // wildcard triggers full scan
*
* // GOOD: Uses LIVEINSTANCES, avoids ExternalView scan
* Criteria criteria = new Criteria();
* criteria.setInstanceName("instance123");
* criteria.setDataSource(DataSource.LIVEINSTANCES);
* </pre>
*/
public class CriteriaEvaluator {
private static Logger logger = LoggerFactory.getLogger(CriteriaEvaluator.class);
public static final String MATCH_ALL_SYM = "%";

/**
* Examine persisted data to match wildcards in {@link Criteria}
*
* <p><b>PERFORMANCE WARNING:</b> Using {@link DataSource#EXTERNALVIEW} with wildcard resource
* names (or unspecified resource) will scan ALL ExternalView znodes, even when targeting specific
* instances. At high cardinality, this can cause severe performance degradation. Prefer
* {@link DataSource#LIVEINSTANCES} when resource/partition filtering is not needed.
*
* @param recipientCriteria Criteria specifying the message destinations
* @param manager connection to the persisted data
* @return map of evaluated criteria
Expand All @@ -56,6 +95,12 @@ public List<Map<String, String>> evaluateCriteria(Criteria recipientCriteria,

/**
* Examine persisted data to match wildcards in {@link Criteria}
*
* <p><b>PERFORMANCE WARNING:</b> Using {@link DataSource#EXTERNALVIEW} with wildcard resource
* names (or unspecified resource) will scan ALL ExternalView znodes, even when targeting specific
* instances. At high cardinality, this can cause severe performance degradation. Prefer
* {@link DataSource#LIVEINSTANCES} when resource/partition filtering is not needed.
*
* @param recipientCriteria Criteria specifying the message destinations
* @param accessor connection to the persisted data
* @return map of evaluated criteria
Expand Down
Loading