DistCp and disaster recovery

A second cluster only protects you if it holds the right data. This lesson copies a production folder to a real DR cluster with DistCp, catches the classic silent skip, keeps the copy in sync with -update, -delete and snapshot diffs, and runs a failover drill that shows exactly what a disaster would cost.

Module 12 · Multiple clusters and operations⏱ 32 minAdvancedTwo real clustersArchitecture diagram + 2 animationsRuns in your browser (Python)8 practice problems
1 The story

A second cluster, and the menu that didn't arrive

The college now runs two clusters: prod on campus and a DR (disaster recovery) cluster in another building. Every night Kabir copies /prod/canteen to DR with DistCp. One morning the canteen raises the price of chai from ₹15 to ₹18. The nightly copy finishes "successfully", yet the DR menu still says ₹15. Same file name, same size (143 bytes), so plain DistCp skipped it without a word.

PROD · hdfs://namenode canteen_orders.csvmenu.csv chai,18 143 Borders_day31.csv (new)feedback.txt (deleted) DR · hdfs://nn-canteen canteen_orders.csvmenu.csv chai,15 143 Borders_day31.csv ✓feedback.txt still here hadoop distcp (no options) Files Copied=1 · Files Skipped=4 distcp -update -delete size + checksum → menu fixed, file removed Real run between two lab clusters. "Success" only means the copy did what you asked. myphatshala.in
Riya

Sir, DistCp said it succeeded. How can DR be wrong?

Arjun Sir

Without options DistCp only asks "does a file with this name already exist there?". If yes, it skips it. It never looked inside menu.csv. With -update it compares size and checksum, and with -delete it also removes what prod deleted.

Kabir

And if the campus floods tonight, DR is our only copy. Whatever wasn't synced yet is simply gone.

Arjun Sir

That loss window has a name: the RPO. Today we copy between two real clusters, fix the sync, use snapshots so a nightly sync copies only what changed, and run a failover drill to see exactly what DR would miss.

2 Definition

DistCp and disaster recovery

Formal definition (write this in exams)

DistCp (distributed copy) is a Hadoop tool that copies large directory trees within or between clusters by running a map-only MapReduce job: the client builds a listing of source files, splits it into chunks, and each map task copies its files directly from source DataNodes to destination DataNodes, verifying checksums. Options control incremental behaviour (-update copies files whose size or checksum differ, -overwrite copies unconditionally, -delete removes target files missing from the source, -diff applies a snapshot difference), what metadata is preserved (-p), parallelism (-m) and bandwidth (-bandwidth). Disaster recovery (DR) is the set of plans, copies and procedures that let a service resume at another site after the primary site is lost. It is measured by the recovery point objective (RPO), the maximum acceptable data loss expressed as time, and the recovery time objective (RTO), the maximum acceptable time to restore service.

In simple words

DistCp is cp for clusters: many map tasks copy files in parallel. DR means keeping a second copy far away and knowing how to switch to it. RPO = how much data you can lose; RTO = how long you can be down.

Words you'll meet in this lesson

DistCpDistributed copy: a map-only MapReduce job that copies files.
-updateCopy only files that are missing or differ in size or checksum.
-deleteRemove target files that no longer exist at the source.
-diff s1 s2Sync using the difference between two source snapshots.
DR siteA second cluster in another place that can take over.
RPORecovery point objective: how much recent data you may lose.
RTORecovery time objective: how long until service is back.
Failover drillA planned rehearsal of switching to DR.

Architecture at a glance

Our lab: two clusters on separate networks. DistCp's map tasks run on prod's YARN and write straight into the DR cluster's DataNodes. Snapshots on both sides make each night's sync small.

PROD site · lab8 NameNode/prod/canteen · s1 s2 ResourceManagerruns the DistCp job worker1 worker2 worker3 copy map copy map copy map DataNodeDataNodeDataNode scheduler (cron / Oozie / Airflow): every night 01:00 DR site · lab72 NameNode nn-canteen/dr/canteen · s1 (s2 after sync) DN DN DN same data, other building can run jobs if prod is lost listing blocks last sync 01:00 disaster 19:00 RPO window: data written here exists only on prod myphatshala.in

From our lab (two Hadoop 3.5.0 clusters)

First full copy5 files, 169,964,453 bytes, 5 map tasks, 25.5 s
Plain re-runFiles Copied=1, Files Skipped=4: the changed menu.csv (same 143 bytes) was skipped and the deleted file stayed
-update / -deleteCopied only menu.csv (143 bytes); then removed feedback.txt on DR
Snapshot diff-update -diff s1 s2: 1 file (28,086 bytes), 1 map, 15.1 s; a rename was replayed as a rename
Throttle-bandwidth 1 on 19.4 MB: 34.2 s
DR drillThe Lesson 8.1 report ran on DR data with identical results; a file written after the last sync was missing on DR

DR at three levels

Pick your level. New to this? Start at Beginner and climb.

Beginner A spare key with a neighbour

  • You keep a spare house key with a neighbour in another street. If you lose yours, you can still get in: that is DR.
  • If you changed the lock last week and forgot to give the neighbour the new key, the spare is useless. A stale copy is the risk DistCp -update protects against.
  • How old the spare may be is the RPO; how long it takes to walk over and get it is the RTO.

Intermediate How DistCp decides what to copy

  • No option: if a file with the same name exists at the target, it is skipped. Our changed menu.csv was skipped.
  • -update: copy if the target is missing, or if size or checksum differ. menu.csv was copied (143 bytes).
  • -overwrite: copy everything again, always.
  • -delete (with -update or -overwrite): delete target files not present at the source.
  • -diff s1 s2: ask the NameNode what changed between two snapshots, replay renames and deletes, copy only new or modified files.

Advanced What production DR adds

  • Metadata too: Hive/Impala tables need their metastore replicated (schemas, partitions), not just HDFS files.
  • Checksums across settings: HDFS file checksums depend on block size and checksum type. Copy with -pb (preserve block size) or use dfs.checksum.combine.mode=COMPOSITE_CRC; -skipcrccheck hides real corruption and is a last resort.
  • Across versions and clouds: webhdfs:// works between different Hadoop versions; s3a:// and abfs:// targets copy to cloud storage.
  • Drills: a DR plan that was never tested is a guess. Teams run the real jobs on DR a few times a year and measure the actual RTO.

Exam tip: For "What is DistCp and how is it used for DR?", say: a map-only MapReduce job that copies files in parallel between clusters; incremental with -update (size + checksum) and -delete; snapshot-based with -diff; and define RPO and RTO with one example.

3 Types and ways to use it

DistCp options and DR designs

OptionWhat it doesOur lab
(none)Copy files whose name doesn't exist at the targetSkipped the changed menu.csv
-updateCopy if missing or size/checksum differCopied 143 bytes
-overwriteCopy everything, always(not used; would copy 162 MB)
-deleteRemove target files missing at sourceRemoved feedback.txt
-diff s1 s2Replay a snapshot diff; needs s1 on both sides1 file, 1 map, rename kept
-p[rbugpcaxt]Preserve replication, block size, user, group, permissions, checksum type, ACLs, xattrs, timesUse -pb when block sizes differ
-m N / -strategy dynamicNumber of maps; dynamic lets fast maps take more chunksOne map per file here
-bandwidth MBLimit each map's speed, to protect the network1 MB/s: 34.2 s for 19.4 MB
-i / -atomicIgnore failures / copy to a temp folder then move in one step-

DR designs

Backup only

Copies on cheaper storage (another cluster, cloud). Protects data, but restoring and rebuilding compute takes days: long RTO.

cheapest

Active–passive

A DR cluster kept in sync (nightly or hourly DistCp). Jobs move there on failover. RPO = sync interval.

most common

Active–active

Both sites ingest and serve; data is written to both or replicated continuously. Low RPO/RTO, highest cost and complexity.

critical systems

Cloud as DR

DistCp to s3a:// or abfs://; spin up a cloud cluster only during a disaster.

pay when used

Animated example: when Chennai floods

An insurer's DR night 6 steps
Animated example Chennai (prod) Pune (DR) claims, policies40 TB in HDFS copy as of 01:00 01:00 · nightly distcp -update -diffonly the day's changes travel (about 300 GB) 09:00–18:00 · a normal daynew claims are written only in Chennai FLOODED 19:00 19:00 · power and network lost in Chennaithe on-call team opens the DR runbook jobs + users → Pune 19:40 · DNS and job configspoint to the DR NameNode lost: claims written 01:00–19:00 (RPO = 18 h) 20:30 · reports run in PuneRTO achieved: 1 h 30 min next quarter: hourly snapshots + diff syncRPO drops from 18 h to about 1 h myphatshala.in

Run DistCp from the cluster with spare YARN capacity and, when versions differ, from the newer one, reading the older cluster over webhdfs://. In our lab the maps ran on prod's workers, the only machines that could reach both clusters.

4 Step by step

Two clusters, one nightly sync, one drill

Prod is the Module 8 cluster; DR is the federation cluster from Lesson 7.2 (hdfs://nn-canteen:8020). Commands run on a prod worker, which join_clusters.sh connects to both networks.

  1. First full copy

    hadoop distcp /prod/canteen hdfs://nn-canteen:8020/dr/
    exit 0, took 25540 ms Bytes Copied=169964453 Files Copied=5 Launched map tasks=5
    A map-only job: the client listed 5 files, YARN ran 5 copy maps on prod's workers, and each map streamed blocks from prod DataNodes into DR DataNodes, then compared checksums.
  2. A day later: plain DistCp again

    hadoop distcp /prod/canteen hdfs://nn-canteen:8020/dr/
    Bytes Copied=70147 Files Copied=1 Files Skipped=4 143 /dr/canteen/menu.csv 5093962 /dr/canteen/feedback.txt
    Only the new file was copied. The changed menu.csv (same name, same size) and the deleted feedback.txt were left as they were, and the job still reported success.
  3. -update, then -update -delete

    hadoop distcp -update /prod/canteen hdfs://nn-canteen:8020/dr/canteen
    hadoop distcp -update -delete /prod/canteen hdfs://nn-canteen:8020/dr/canteen
    hdfs dfs -cat hdfs://nn-canteen:8020/dr/canteen/menu.csv | head -1
    Bytes Copied=143 Files Copied=1 Files Skipped=4 ... Files Skipped=5 chai,drink,18,A
    With -update, source and target paths are the folders themselves. Size was equal, but the checksums differed, so menu.csv was copied. -delete then removed feedback.txt from DR.
  4. Sync only a snapshot difference

    hdfs dfs -createSnapshot /prod/canteen s1     # and s1 on the DR copy
    hdfs dfs -mv  .../orders_day31.csv .../orders_2026-10-31.csv ; put orders_2026-11-01.csv
    hdfs dfs -createSnapshot /prod/canteen s2
    hdfs snapshotDiff /prod/canteen s1 s2
    hadoop distcp -update -diff s1 s2 /prod/canteen hdfs://nn-canteen:8020/dr/canteen
    M . + ./orders_2026-11-01.csv R ./orders_day31.csv -> ./orders_2026-10-31.csv exit 0, took 15085 ms Bytes Copied=28086 Files Copied=1 Launched map tasks=1
    DistCp asked the NameNode for the diff instead of comparing every file. The rename was applied as a rename on DR (no bytes copied) and only the new 28 KB file travelled. On millions of files this is the difference between hours of listing and minutes.
  5. Throttle the copy

    hadoop distcp -bandwidth 1 /prod/canteen/student_orders.csv hdfs://nn-canteen:8020/dr/throttled.csv
    exit 0, took 34192 ms Bytes Copied=19418699
    At 1 MB/s per map, 19.4 MB needs at least 19 s of copying plus job start-up. Throttling protects the link between sites during business hours.
  6. Disaster drill

    hadoop jar mr.jar ItemRevenue hdfs://nn-canteen:8020/dr/canteen/canteen_orders.csv hdfs://nn-canteen:8020/dr/report
    hdfs dfs -put day32.csv /prod/canteen/orders_2026-11-02.csv      # written after the last sync
    completed successfully chai 50170 752550 dosa 49948 2247660 idli 49984 1499520 prod files: 7 DR files: 6 missing on DR: orders_2026-11-02.csv
    The Lesson 8.1 report gives identical numbers from DR data. But anything written after the last sync exists only on prod: if prod were gone now, that file would be lost. That gap is the RPO.

Never point a scheduled sync at the wrong direction or the wrong folder with -delete: it will faithfully delete everything the source doesn't have. Test every new sync command on a scratch folder first, and keep snapshots on the target so a bad run can be undone.

5 See it happen

Our sync, run by run

Six steps from the lab: full copy, silent skip, update, delete, snapshot diff, drill.

Prod → DR 6 steps
What you see hadoop@worker1 : ~ $ hadoop distcp /prod/canteen dr:/dr/Files Copied=5Bytes Copied=169964453took 25540 ms, 5 maps $ hadoop distcp /prod/canteen dr:/dr/Files Copied=1Files Skipped=4dr menu.csv: chai,drink,15 $ hadoop distcp -update ...Files Copied=1Bytes Copied=143dr menu.csv: chai,drink,18 $ hadoop distcp -update -delete ...Files Skipped=5feedback.txt removed on DR $ hadoop distcp -update -diff s1 s2 ...R orders_day31 -> orders_2026-10-31Files Copied=1 Bytes Copied=28086took 15085 ms, 1 map $ hadoop jar mr.jar ItemRevenue dr:...completed successfullychai 50170 752550missing on DR: orders_2026-11-02.csv myphatshala.in
Behind the screen PROD DR canteen_ordersstudent_ordersorders_x30menu (chai 15)feedbackcanteen_ordersstudent_ordersorders_x30menu (chai 15)feedback5 maps, each copies one file, then checks checksums … 3 big filesmenu (chai 18)orders_day31 (new)feedback… 3 big filesmenu (chai 15)orders_day31 ✓feedbackno option: a name that exists at DR is skipped menu: 143 B, crc Amenu: 143 B, crc B-update: same size, different checksum → copy feedback-delete: DR now mirrors prod exactly snapshot s1 → s2R day31 → 2026-10-31+ 2026-11-01rename applied2026-11-01 ✓the NameNode's diff replaces a full comparison 7 files+ 2026-11-02 (after sync)6 filesreport ✓ same numbersthe unsynced file is the RPO: lost if prod dies now myphatshala.in
6 Real-world use

DistCp and DR at work

1. Bank: regulator-mandated DR

Banks must show a tested DR plan. Transaction history in HDFS is synced to a second data centre several times a day, and failover drills are run and reported every quarter.

Hourly snapshots→distcp -diff→DR site + drill report
CDH → CDP

2. Telecom: migrating to a new cluster

When a telecom moves petabytes of call records from an old Hadoop distribution to a new cluster, DistCp over webhdfs:// copies data while both run; repeated -update runs shrink the final cut-over window.

Old cluster→distcp -update (repeat)→New cluster

3. E-commerce: archive to the cloud

Old order data is copied to object storage (s3a:// or abfs://) with DistCp, verified, and then deleted from the on-prem cluster to free disks.

HDFS (cold data)→distcp → s3a://→Cheap object storage
prod → dev

4. Analytics team: refreshing a test cluster

A masked sample of production data is copied to the development cluster every week so new jobs are tested on realistic data without touching prod.

Prod (masked)→distcp -update -delete→Dev cluster
2 regions

5. Healthcare: two regions, active–active

A hospital chain ingests records in two regions and replicates each region's data to the other, so either site can serve all reports if one goes down.

Region A ⇄ Region B→scheduled two-way sync→Either site serves

Simplified; organisations differ in tools and policies.

7 Run the code

Decide like DistCp

This model reproduces our second run. Each file has a size and a checksum. Plain DistCp only checks whether the name exists at the target; -update also compares size and checksum; -delete removes target files the source no longer has.

prod = {"canteen_orders.csv": (4692009, "c1"), "menu.csv": (143, "m2"),
        "orders_day31.csv": (70147, "d1"), "orders_x30.csv": (140759640, "x1"),
        "student_orders.csv": (19418699, "s1")}
dr = {"canteen_orders.csv": (4692009, "c1"), "menu.csv": (143, "m1"),
      "feedback.txt": (5093962, "f1"), "orders_x30.csv": (140759640, "x1"),
      "student_orders.csv": (19418699, "s1")}

def plan(src, dst, update=False, delete=False):
    copy, skip = [], []
    for name, (size, crc) in src.items():
        if name not in dst:
            copy.append(name)
        elif update and dst[name] != (size, crc):   # size OR checksum differs
            copy.append(name)
        else:
            skip.append(name)
    gone = [n for n in dst if n not in src] if delete else []
    return copy, skip, gone

for opts in [{}, {"update": True}, {"update": True, "delete": True}]:
    c, s, g = plan(prod, dr, **opts)
    print(opts or "no options", "-> copy", c, "| skipped", len(s), "| delete", g)
no options -> copy ['orders_day31.csv'] | skipped 4 | delete [] {'update': True} -> copy ['menu.csv', 'orders_day31.csv'] | skipped 3 | delete [] {'update': True, 'delete': True} -> copy ['menu.csv', 'orders_day31.csv'] | skipped 3 | delete ['feedback.txt']
  • elif update and dst[name] != (size, crc): # size OR checksum differsOur menu.csv: same 143 bytes, different checksum. Only -update notices.
  • gone = [n for n in dst if n not in src] if delete else []-delete is what removed feedback.txt from the DR copy.

Run it on your PC: two clusters, one sync, one drill

You need the Module 8 lab (prod) and the Lesson 7.2 federation lab (DR) running together; stop the Module 5 lab to save memory. join_clusters.sh connects only prod's three workers to the DR network: both clusters use names like namenode, and when we joined every container to both networks, a client resolved resourcemanager to the wrong network and got "Connection refused". Then run distcp_lab.sh inside lab8-worker1-1. It takes about 4 minutes.

Connect the clusters, then sync and drill

# ---- join_clusters.sh (run on your PC) ----
# join_clusters.sh: let the lab8 workers (where DistCp's map tasks run) reach the second cluster.
# Only the workers join: the clusters both use names like "namenode", and a container on two networks
# can answer to the wrong address. Run on your PC.
docker compose -p lab72 start                       # the Lesson 7.2 federation cluster = our "DR" site
for c in worker1 worker2 worker3; do docker network connect lab72_default lab8-$c-1; done
docker exec lab8-worker1-1 getent hosts namenode resourcemanager nn-canteen
docker cp lab8-namenode-1:/tmp/mr/mr.jar /tmp/mr.jar && docker cp /tmp/mr.jar lab8-worker1-1:/tmp/mr.jar

# ---- distcp_lab.sh ----
# distcp_lab.sh: copy a production folder to a second (DR) cluster, keep it in sync, then fail over.
# PROD = the Module 8 cluster (hdfs://namenode). DR = the federation cluster of Lesson 7.2 (hdfs://nn-canteen:8020).
# The lab8 workers are joined to the DR cluster's Docker network (join_clusters.sh). Run inside lab8-worker1-1.
DR=hdfs://nn-canteen:8020
P=/prod/canteen
D=$DR/dr/canteen
run() { local name=$1; shift; local s=$(date +%s%N)
  hadoop distcp "$@" > /tmp/$name.log 2>&1; echo "   exit $?, took $(( ($(date +%s%N) - s) / 1000 / 1000 )) ms"
  grep -E "Bytes Copied|Bytes Skipped|Files Copied|Files Skipped|DIR_COPY|Launched map tasks|Deleted|Files Deleted|Bytes Expected" /tmp/$name.log | sed 's/^\s*/   /' | sort -u; }
hdfs dfs -rm -r -f -skipTrash $P $DR/dr > /dev/null 2>&1
hdfs dfs -mkdir -p $P $DR/dr
hdfs dfs -cp /user/hadoop/data/{canteen_orders.csv,student_orders.csv,menu.csv,feedback.txt,orders_x30.csv} $P/
echo "== 0. what we protect (prod)"
hdfs dfs -count -h $P
echo "== 1. first full copy to the DR cluster (one map per file here)"
run d1 $P $DR/dr/
hdfs dfs -count -h $D
echo "== 2. a day later: one new file, one changed file, one deleted file"
hdfs dfs -cat $P/canteen_orders.csv | head -5001 > /tmp/day31.csv; hdfs dfs -put -f /tmp/day31.csv $P/orders_day31.csv
hdfs dfs -cat $P/menu.csv | sed 's/^chai,drink,15/chai,drink,18/' > /tmp/menu.csv; hdfs dfs -put -f /tmp/menu.csv $P/menu.csv
hdfs dfs -rm -skipTrash $P/feedback.txt > /dev/null
echo "-- plain distcp again (no -update): the existing files are NOT replaced"
run d2a $P $DR/dr/
hdfs dfs -ls $D | awk '{print "   ", $5, $8}' | sed "s#$DR##"
echo "-- distcp -update: copy only what is new or different"
run d2 -update $P $D
echo "-- distcp -update -delete: also remove what prod deleted"
run d3 -update -delete $P $D
hdfs dfs -ls $D | awk '{print "   ", $5, $8}' | sed "s#$DR##"
echo "-- is the price change there?"; hdfs dfs -cat $D/menu.csv | head -1
echo "== 3. snapshot-based sync: only the difference between two snapshots"
hdfs dfsadmin -allowSnapshot $P > /dev/null; hdfs dfsadmin -fs $DR -allowSnapshot /dr/canteen > /dev/null
hdfs dfs -createSnapshot $P s1 > /dev/null; hdfs dfs -createSnapshot $D s1 > /dev/null
hdfs dfs -mv $P/orders_day31.csv $P/orders_2026-10-31.csv
hdfs dfs -cat $P/canteen_orders.csv | head -2001 | tail -2000 > /tmp/day32.csv; hdfs dfs -put /tmp/day32.csv $P/orders_2026-11-01.csv
hdfs dfs -createSnapshot $P s2 > /dev/null
hdfs snapshotDiff $P s1 s2 2>/dev/null | sed 's/^/   /'
run d4 -update -diff s1 s2 $P $D
hdfs dfs -ls $D | awk '{print "   ", $5, $8}' | sed "s#$DR##"
echo "== 4. throttle: -bandwidth 1 (MB/s per map) on the 19 MB student_orders.csv"
run d5 -bandwidth 1 $P/student_orders.csv $DR/dr/throttled.csv
echo "== 5. disaster drill: prod is down, run the report on the DR cluster"
hdfs dfs -rm -r -f -skipTrash $DR/dr/report > /dev/null 2>&1
hadoop jar /tmp/mr.jar ItemRevenue $D/canteen_orders.csv $DR/dr/report > /tmp/dr_job.log 2>&1
grep -oE "completed successfully|failed with state [A-Z]+" /tmp/dr_job.log
hdfs dfs -cat $DR/dr/report/part-r-00000 | head -3
echo "-- recovery point: what DR has vs prod right now"
hdfs dfs -put -f /tmp/day32.csv $P/orders_2026-11-02.csv     # written after the last sync
echo "   prod files: $(hdfs dfs -ls $P | grep -c '^-')   DR files: $(hdfs dfs -ls $D | grep -c '^-')   missing on DR: $(diff <(hdfs dfs -ls $P | grep '^-' | awk -F/ '{print $NF}') <(hdfs dfs -ls $D | grep '^-' | awk -F/ '{print $NF}') | grep '^<' | cut -c3-)"

# Run:  docker cp distcp_lab.sh lab8-worker1-1:/tmp/ && docker exec lab8-worker1-1 bash /tmp/distcp_lab.sh
== 0. what we protect (prod) 1 5 162.1 M /prod/canteen == 1. first full copy to the DR cluster (one map per file here) exit 0, took 25540 ms Bytes Copied=169964453 Bytes Expected=169964453 DIR_COPY=1 Files Copied=5 Launched map tasks=5 1 5 162.1 M hdfs://nn-canteen:8020/dr/canteen == 2. a day later: one new file, one changed file, one deleted file -- plain distcp again (no -update): the existing files are NOT replaced exit 0, took 19796 ms Bytes Copied=70147 Bytes Expected=70147 Bytes Skipped=164870491 DIR_COPY=1 Files Copied=1 Files Skipped=4 Launched map tasks=3 4692009 /dr/canteen/canteen_orders.csv 5093962 /dr/canteen/feedback.txt 143 /dr/canteen/menu.csv 70147 /dr/canteen/orders_day31.csv 140759640 /dr/canteen/orders_x30.csv 19418699 /dr/canteen/student_orders.csv -- distcp -update: copy only what is new or different exit 0, took 20135 ms Bytes Copied=143 Bytes Expected=143 Bytes Skipped=164940495 Files Copied=1 Files Skipped=4 Launched map tasks=3 -- distcp -update -delete: also remove what prod deleted exit 0, took 24772 ms Bytes Skipped=164940638 Files Skipped=5 Launched map tasks=4 4692009 /dr/canteen/canteen_orders.csv 143 /dr/canteen/menu.csv 70147 /dr/canteen/orders_day31.csv 140759640 /dr/canteen/orders_x30.csv 19418699 /dr/canteen/student_orders.csv -- is the price change there? chai,drink,18,A == 3. snapshot-based sync: only the difference between two snapshots Difference between snapshot s1 and snapshot s2 under directory /prod/canteen: M . + ./orders_2026-11-01.csv R ./orders_day31.csv -> ./orders_2026-10-31.csv exit 0, took 15085 ms Bytes Copied=28086 Bytes Expected=28086 Files Copied=1 Launched map tasks=1 4692009 /dr/canteen/canteen_orders.csv 143 /dr/canteen/menu.csv 70147 /dr/canteen/orders_2026-10-31.csv 28086 /dr/canteen/orders_2026-11-01.csv 140759640 /dr/canteen/orders_x30.csv 19418699 /dr/canteen/student_orders.csv == 4. throttle: -bandwidth 1 (MB/s per map) on the 19 MB student_orders.csv exit 0, took 34192 ms Bytes Copied=19418699 Bytes Expected=19418699 Files Copied=1 Launched map tasks=1 == 5. disaster drill: prod is down, run the report on the DR cluster completed successfully chai 50170 752550 dosa 49948 2247660 idli 49984 1499520 -- recovery point: what DR has vs prod right now prod files: 7 DR files: 6 missing on DR: orders_2026-11-02.csv

Real output. Timings vary. Notice step 2: plain DistCp reports success with "Files Skipped=4" while the DR menu still has the old price.

8 Line by line

Applying a snapshot diff

Follow a DR folder as the diff is applied: a rename moves a name without copying bytes, and only the new file is copied.

Worked examples: real problems, solved and traced in memory

Four DR calculations from different industries: RPO and RTO, the sync window, snapshot savings and cost.

Example 1BeginnerBanking · RPO/RTO

Does the nightly sync meet the regulator?

Problem statement

A bank's policy says RPO ≤ 4 hours and RTO ≤ 2 hours. Today it syncs once a night at 02:00 and failover takes 90 minutes. What is the worst-case RPO, and does it comply?

Input
sync every 24 h · failover 90 min · limits 4 h / 2 h
Expected output
RPO 24 h (limit 4) -> FAIL; RTO 1.5 h (limit 2) -> OK
syncs needed per day for RPO 4 h: 6

Approach

  1. Worst case: disaster just before the next sync.
  2. RPO = sync interval; RTO = failover time.
  3. Compare with the limits.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 2IntermediateTelecom · bandwidth

How long does the first copy take?

Problem statement

A telecom starts DR for 1.2 PB of call records. The inter-site link is 10 Gbit/s; DistCp may use 60% of it. How many days does the first full copy take?

Input
1.2 PB · 10 Gbit/s · 60% usable
Expected output
20.8 days

Approach

  1. Convert the link to bytes per second.
  2. Divide data by usable rate.
  3. Convert to days.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 3IntermediateE-commerce · snapshots

How much listing does a snapshot diff save?

Problem statement

A folder holds 50 million files; 20,000 change per day. A plain -update run must compare every file (say 2 ms of NameNode work per file on each side); a -diff run asks only for the changes. Compare the comparison time.

Input
50,000,000 files · 20,000 changes · 2 ms per file
Expected output
-update compare: 56 h   -diff: 1.3 min

Approach

  1. -update: every file is listed and compared on both clusters.
  2. -diff: the NameNode returns only the changes.
  3. Compare.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 4AdvancedInsurance · cost

Backup, active–passive or active–active?

Problem statement

An insurer loses about ₹5 lakh of business per hour of downtime and ₹2 lakh per hour of lost data. Option A, cloud backup: ₹40 lakh/yr, RTO 48 h, RPO 24 h. Option B, active–passive DR: ₹1.6 crore/yr, RTO 2 h, RPO 1 h. Option C, active–active: ₹4 crore/yr, RTO 0.1 h, RPO 0.1 h. Expect one disaster every 5 years. Which is cheapest in total?

Input
3 options · 0.2 disasters per year
Expected output
A backup           run   40 lakh + expected loss  57.6 lakh =   97.6 lakh/yr
B active-passive   run  160 lakh + expected loss   2.4 lakh =  162.4 lakh/yr
C active-active    run  400 lakh + expected loss   0.1 lakh =  400.1 lakh/yr

Approach

  1. Expected yearly loss = 0.2 × (RTO × downtime cost + RPO × data cost).
  2. Total = running cost + expected loss.
  3. Compare.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

9 Quiz and revision

Check yourself

Quick revision

Lesson 12.2 in one screen

  • DistCp = map-only MapReduce copy; maps copy files and verify checksums.
  • No option: existing names are skipped (our changed menu.csv). -update: size + checksum. -overwrite: always. -delete: mirror deletions.
  • -update -diff s1 s2: apply a snapshot diff (1 file, 1 map, rename replayed in our lab).
  • -p preserves metadata; -pb keeps block size so checksums match; -bandwidth throttles; -m sets maps.
  • RPO = data you can lose (time since last sync); RTO = time to recover.
  • Designs: backup, active–passive, active–active, cloud as DR. Replicate metadata (Hive metastore) too.
  • Test with drills: our report ran on DR with identical results; the unsynced file was missing.

Interview and viva questions

What is DistCp in Hadoop?

DistCp (distributed copy) copies large amounts of data within or between clusters. It runs as a map-only MapReduce job: the client lists the source files, and map tasks copy them in parallel from source DataNodes to destination DataNodes, verifying checksums. It supports incremental copies (-update, -delete), snapshot-based syncs (-diff), preserving metadata (-p) and throttling (-bandwidth).

What is the difference between -update and -overwrite in DistCp?

With -update, a file is copied only if it is missing at the target or its size or checksum differs. With -overwrite, every file is copied again even if it is identical. Without either, files whose names already exist at the target are skipped, even if their content changed.

What are RPO and RTO?

The recovery point objective (RPO) is the maximum acceptable amount of data loss, measured as the time since the last good copy. The recovery time objective (RTO) is the maximum acceptable time to restore service after a disaster. Sync frequency drives RPO; automation and drills drive RTO.

How do you do disaster recovery for HDFS?

Keep a second cluster (or cloud storage) at another site, sync data with scheduled DistCp runs (ideally snapshot-based with -diff), replicate metadata such as the Hive metastore, document a failover runbook (DNS, job configs, access) and test it with regular drills. Commercial tools (for example Cloudera Replication Manager) automate the same steps.

Why does DistCp fail with a checksum mismatch between clusters?

HDFS file checksums are computed from block-level checksums, so they depend on block size and checksum type. If source and target use different settings, the checksums differ even for identical data. Preserve block size and checksum type (-pbc) or use the COMPOSITE_CRC combine mode; use -skipcrccheck only when you verify the data another way.

Practice problems

DR exercises with the real numbers from our two clusters.

P1Easy

Copy speed

The first copy moved 169,964,453 bytes in 25,540 ms. What was the effective rate in MB/s?

Input
bytes · ms
Expected output
6.3 MB/s
Show solution and explanation
print(round(169964453 / 2**20 / 25.540, 1), "MB/s")
6.3 MB/s

How it works: About 6.3 MB/s, including job start-up; the copy itself was faster.

P2Easy

What was skipped?

Run 2 copied 70,147 bytes and skipped 164,870,491. How many bytes were really changed on prod, and how many of the skipped bytes were stale?

Input
Bytes Copied / Bytes Skipped
Expected output
copied 70147 | stale but skipped: menu.csv 143 bytes
Show solution and explanation
print("copied", 70147, "| stale but skipped: menu.csv", 143, "bytes")
copied 70147 | stale but skipped: menu.csv 143 bytes

How it works: Only 143 bytes were stale, but they held the new price. A tiny skip can be a business error.

P3Easy

Throttle check

At -bandwidth 1 (MB/s), what is the minimum time to copy 19,418,699 bytes? The run took 34.2 s. Where did the rest go?

Input
19.4 MB · 1 MB/s
Expected output
18.5 s minimum
Show solution and explanation
print(round(19418699 / 2**20, 1), "s minimum")
18.5 s minimum

How it works: About 18.5 s of copying; the rest was job submission, container start-up and checksum verification.

P4Medium

RPO for a schedule

Syncs run at 00:00, 06:00, 12:00 and 18:00. A disaster happens at 17:30. How much data is lost, and what is the worst case?

Input
4 syncs a day
Expected output
lost: 5.5 h | worst case: 6 h
Show solution and explanation
syncs = [0, 6, 12, 18]
d = 17.5
print("lost:", d - max(s for s in syncs if s <= d), "h | worst case: 6 h")
lost: 5.5 h | worst case: 6 h

How it works: 5.5 hours this time; the worst case is a full interval of 6 hours.

P5Medium

Mirror check

Write a function that lists files to copy, files to delete and files that are stale-but-skipped for a plain run.

Input
two dicts name → checksum
Expected output
copy: ['c']
stale but skipped: ['b']
left behind: ['d']
Show solution and explanation
src = {"a": "1", "b": "2", "c": "3"}
dst = {"a": "1", "b": "9", "d": "4"}
print("copy:", [n for n in src if n not in dst])
print("stale but skipped:", [n for n in src if n in dst and src[n] != dst[n]])
print("left behind:", [n for n in dst if n not in src])
copy: ['c'] stale but skipped: ['b'] left behind: ['d']

How it works: c is copied, b is stale but skipped, d stays behind: the three problems -update and -delete solve.

P6Medium

Maps for a big copy

DistCp splits 120,000 files totalling 30 TB over -m 200 maps. Roughly how much does each map copy, and how long at 80 MB/s per map?

Input
30 TB · 200 maps · 80 MB/s
Expected output
154 GB per map, about 0.5 h
Show solution and explanation
per_map_gb = 30 * 1024 / 200
print(f"{per_map_gb:.0f} GB per map, about {per_map_gb * 1024 / 80 / 3600:.1f} h")
154 GB per map, about 0.5 h

How it works: About 154 GB per map and 0.5 hours, if the network and both clusters can sustain 16 GB/s in total, which they often can't: throttle and schedule.

P7Business problem

Is a drill worth it?

A failover drill costs one Saturday for 6 engineers (₹15,000 each). Without drills, the team estimates RTO doubles from 2 h to 4 h in a real disaster, at ₹5 lakh per hour. With one disaster every 5 years, is a drill every quarter worth it?

Input
4 drills/yr · ₹15,000 × 6 · 0.2 disasters/yr
Expected output
drills Rs 360,000 vs expected saving Rs 200,000 per year
Show solution and explanation
drills = 4 * 6 * 15000
saved = 0.2 * (4 - 2) * 500000
print(f"drills Rs {drills:,} vs expected saving Rs {saved:,.0f} per year")
drills Rs 360,000 vs expected saving Rs 200,000 per year

How it works: ₹3.6 lakh vs ₹2 lakh on these illustrative numbers. Teams usually still drill, because a failed real failover can be far worse than the average, and regulators often require it.

P8Advanced

Build a copy plan from a snapshot diff

Given a snapshotDiff report with +, -, M and R lines, produce the list of DR actions and the bytes to copy.

Input
diff lines + sizes
Expected output
[('copy', './a.csv'), ('delete', './old.csv'), ('rename', './x.csv', './y.csv'), ('copy', './menu.csv')] 28229 bytes
Show solution and explanation
diff = ["M\t.", "+\t./a.csv", "-\t./old.csv", "R\t./x.csv -> ./y.csv", "M\t./menu.csv"]
size = {"./a.csv": 28086, "./menu.csv": 143}
plan, nbytes = [], 0
for line in diff:
    kind, path = line.split("\t")
    if path == ".":
        continue
    if kind in "+M":
        plan.append(("copy", path)); nbytes += size[path]
    elif kind == "-":
        plan.append(("delete", path))
    elif kind == "R":
        plan.append(("rename",) + tuple(path.split(" -> ")))
print(plan, nbytes, "bytes")
[('copy', './a.csv'), ('delete', './old.csv'), ('rename', './x.csv', './y.csv'), ('copy', './menu.csv')] 28229 bytes

How it works: Copy a.csv and menu.csv (28,229 bytes), delete old.csv, rename x.csv to y.csv: everything else is untouched.

Real-world scenario questions (asked in company interviews)

DistCp and DR questions come up in data platform and Hadoop admin interviews.

Tools · basicsFresher

"How do you copy data between two Hadoop clusters?"

A standard question for any Hadoop role.

The interviewer is checking: DistCp and its key options.

Show a strong answer
  • Use DistCp: a map-only MapReduce job that copies files in parallel and verifies checksums.
  • For repeated syncs use -update (size + checksum) and -delete; for big folders use snapshots with -diff.
  • Throttle with -bandwidth, preserve metadata with -p, use webhdfs:// across Hadoop versions.
Incident · dataExperienced

The DR copy has old data, but every nightly job "succeeded"

An auditor finds that a reference table on DR is three months out of date.

The interviewer is checking: DistCp default semantics and verification.

Show a strong answer
  • Plain DistCp skips files whose names already exist; a file rewritten with the same name was never copied again.
  • Fix the job: -update (and -delete if DR must mirror deletions), or snapshot-based -diff syncs.
  • Add verification: compare file counts and checksums (hdfs dfs -checksum) for key folders, and alert on differences.
Design · DRExperienced

Design DR for a 2 PB cluster with RPO 1 hour

A payments company asks for a plan and its cost drivers.

The interviewer is checking: RPO/RTO thinking and incremental replication.

Show a strong answer
  • Seed DR once (staged DistCp or shipped disks), then hourly snapshots with distcp -update -diff on the changed folders.
  • Replicate the Hive metastore and configs; keep a runbook for DNS, job schedulers and access; run quarterly drills.
  • Size the link for the hourly change rate with headroom; monitor sync lag as a first-class alert.
Concepts · RPO/RTOFresher

"What is the difference between backup and disaster recovery?"

Often asked together with RPO and RTO.

The interviewer is checking: data protection vs service continuity.

Show a strong answer
  • Backup keeps copies of data so it can be restored; restoring and rebuilding compute may take days (long RTO).
  • DR keeps a ready site that can take over the service within the RTO, with data no older than the RPO.
  • Many teams need both: DR for outages, backups or snapshots for mistakes (a bad -delete is replicated to DR too).