利用シーン
適用エンジン:Spark SQLエンジン。
エンジンに複数のタスクを送信する場合、例えば複数のSQLタスクをSpark SQLクラスターに同時に送信する場合、業務上送信されるタスクには前後の依存関係が存在する可能性があるため、エンジンはこれらのタスクをスケジューリングして実行する際、デフォルトでFIFO(先入れ先出し)方式でこれらのタスクをスケジューリングします。
しかし、特定の特殊な状況では、特定のタスクの優先順位を自分で定義する必要がある場合があります。例えば、以下のようなシナリオです:
送信されたタスクの優先度が非常に高く、このタスクを最高優先度で実行する必要があり、クラスターリソースの待ち行列に入れたくない場合です。
送信されたタスクの優先度が非常に低く、このタスクが他のタスクのリソースをできるだけ奪わないようにし、リソースがある場合に実行し、リソースがない場合は待ち行列に入ることを希望する場合です。
カスタムスケジューリングルール
Spark SQLエンジンでは、実行される各SQLタスクJobは複数のTaskの集合であるTaskSetに分割され、私たちのスケジューリングはTaskSetに基づいて行われます。クラスターに空きリソースがあるたびに、すべてのJobのTaskSetからスケジューリングアルゴリズムに従って1つのTaskを選択し、実行に送ります。
私たちのスケジューリングアルゴリズムは、複数のスケジューリングプールを定義し、Job/TaskSetを対応するスケジューリングプールに配置し、スケジューリングプールごとに実行する必要のあるTaskを取得するものです。
スケジューリングプールとその属性
複数のスケジューリングプールを定義でき、各スケジューリングプールには4つの属性があります:
name:スケジュールプールの名前。自由に命名できます。defaultと命名すると、デフォルトのスケジュールプールを意味します。
schedulingMode:スケジューリングルール。FIFOとFAIRの2つのモードをサポートしています。スケジューリングプール内に複数のTaskSetがある場合のスケジューリングアルゴリズムです。
FIFO:TaskSetが送信された順番に従って順次配信されます。
FAIR:複数のTaskSetのタスクが公平に配信されます。具体的な配信ルールは、スケジュールプールのminShareとweight属性に関連しています。
minShare:最小限満たすべきコア数で、0より大きい必要があります。つまり、最小限実行可能なTask数です。スケジューリング時には、このスケジュールプール内で実行されるTask数がminShareに達することを優先的に満たします。
weight:重み付け。重み付けが高いスケジュールプールでは、Taskが優先的にスケジュールされます。minShareを満たした後にのみ重み付けが比較されます。
スケジューリングの設定には、以下の形式のxmlファイルを作成する必要があります:
<?xml version="1.0"?>
<allocations>
<pool name="production">
<schedulingMode>FAIR</schedulingMode>
<weight>1</weight>
<minShare>2</minShare>
</pool>
<pool name="test">
<schedulingMode>FIFO</schedulingMode>
<weight>2</weight>
<minShare>3</minShare>
</pool>
</allocations>
スケジューリング構成の参考例
以下のように3つのスケジューリングプールを設定できます:
デフォルトスケジューリングプール default:schedulingMode = FIFO、weight = 1、minShare =(クラスタコア数 - driverコア数)。このスケジューリングプールはタスクがデフォルトで送信されるスケジューリングプールで、優先度は通常で、先着順に実行され、クラスタのすべての計算リソースを使用できます。
スロータスクスケジューリングプール straggler:schedulingMode = FAIR、weight = 1、minShare = 1。このスケジューリングプールはスロータスクの送信専用で、優先度は通常です。minShare = 1のため、defaultスケジューリングプールに送信された他のタスクのリソースをプリエンプトすることはありません。クラスタにさらに空きリソースがある場合にのみ、stragglerスケジューリングプールのタスクが実行されます。
高優先度スケジューリングプール special:schedulingMode = FIFO、weight = 1000、minShare =(クラスタコア数 - driverコア数)。このスケジューリングプールは、特別な状況で優先的に実行する必要があるタスクに使用されます。ただし、minShareが存在するため、このスケジューリングプールはクラスタの全リソースを占有せず、defaultスケジューリングプールのタスクも引き続き実行されます。一般的な場合、defaultプールとspecialプールは同等の数のTaskを発行します。
16CUのクラスター(ドライバーが4CU)を例にとると、このような参考例の構成は以下の通りです:
<?xml version="1.0"?>
<allocations>
<pool name="default">
<schedulingMode>FIFO</schedulingMode>
<weight>1</weight>
<minShare>12</minShare>
</pool>
<pool name="straggler">
<schedulingMode>FAIR</schedulingMode>
<weight>1</weight>
<minShare>1</minShare>
</pool>
<pool name="special">
<schedulingMode>FIFO</schedulingMode>
<weight>1000</weight>
<minShare>12</minShare>
</pool>
</allocations>
操作手順
1. スケジューリングプールのXMLファイルを準備した後、COSの特定のパス(例:cosn://bucket-appid/fairscheduler.xml)に配置します。
2. エンジン設定に以下の設定を追加します。設定入口のパスは以下の通りです:エンジン > 操作 > パラメータ構成。
パラメータ設定 spark.scheduler.allocation.file に、スケジューリングプールのXMLファイルパス cosn://bucket-appid/fairscheduler.xml を指定します。
この操作にはクラスターの再起動が必要です。
3. タスクを送信する際に、以下のパラメータをタスクパラメータとして指定します。spark.scheduler.pool = 送信先のスケジューリングプール名。defaultスケジューリングプールの場合は、指定する必要はありません。
注意事項
スケジューリングが発生するタイミングは次のとおりです:クラスタに空きリソースがあり、タスクがスケジューリングを必要とする場合。したがって、クラスタがすでにあるタスク(例えば、ある遅いタスク)によって完全に占有されている場合、そのタスクの1つのタスクが実行を完了するまで待たなければならず、その後で他の優先度の高いタスクのスケジューリングが開始されます。そのため、遅いタスクの単一タスクの所要時間は比較的合理的であることが望ましく、そうでない場合、クラスタリソースを長時間占有する可能性があることに注意が必要です。