در این بخش یاد میگیریم پیامهایی که تولید میکنیم دقیقاً کجا و چگونه روی دیسک ذخیره میشوند، ساختار فایلهای لاگ در هر پارتیشن چگونه است و چطور میتوانیم محتوای آنها را مشاهده کنیم.
برای بررسی نحوهی ذخیرهسازی دادهها، ابتدا از یک اسکریپت پایتون ساده برای تولید دادههای تست استفاده کردیم. این اسکریپت با کمک کتابخانههای kafka-python و faker دادههای ساختگی کاربران را بهصورت مداوم در تاپیک users ارسال میکند.
# requirements: kafka-python, faker
from datetime import datetime
import json, random, time, uuid
from kafka import KafkaProducer
from faker import Faker
producer = KafkaProducer(
value_serializer=lambda msg: json.dumps(msg).encode('utf-8'),
key_serializer=str.encode,
bootstrap_servers=['localhost:9092']
)
TOPIC_NAME = 'users'
fake = Faker('en_US')
def generate_user():
return {
'user_id': str(uuid.uuid4()),
'name': fake.name(),
'gender': random.choice(['male', 'female']),
'email': fake.email(),
'location': f"{fake.city()}, {fake.country()}",
'fetched_at': datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
}
while True:
user = generate_user()
producer.send(TOPIC_NAME, value=user, key=user['user_id'])
producer.flush()
print(f"Sent → {user['user_id']}")
time.sleep(0.1)
🔹 نکته: هر پیام دارای key=user_id است، بنابراین Kafka همهی پیامهای دارای یک کلید را به یک پارتیشن ثابت میفرستد.
در فایل Docker Compose، برای کنترل اندازهی فایلهای لاگ از تنظیم زیر استفاده کردیم تا هر ۱ مگابایت داده، یک فایل سگمنت جدید بسازد:
KAFKA_LOG_SEGMENT_BYTES: 1048576
همچنین مسیر ذخیرهسازی دادهها را روی یک دایرکتوری لوکال mount کردیم تا بتوانیم بهسادگی محتوای فایلها را ببینیم:
KAFKA_LOG_DIRS: /var/lib/kafka/data
volumes:
- ./kafka-data:/var/lib/kafka/data
در نتیجه، تمام دادهها در مسیر زیر روی سیستم شما ذخیره میشوند (در پوشهای که فایل داکر کامپوز قرار گرفته است):
./kafka-data/
وقتی تاپیک users با ۴ پارتیشن ساخته شد، Kafka بهصورت خودکار چهار پوشه جدا برای هر پارتیشن ایجاد کرد:
kafka-data/
├── users-0/
├── users-1/
├── users-2/
└── users-3/
هر پوشه، مربوط به یک پارتیشن است و شامل چند فایل کلیدی میشود:
| فایل | توضیح |
|---|---|
.log | دادههای واقعی (پیامها) |
.index | نگاشت آفست منطقی به موقعیت بایت در فایل .log |
.timeindex | نگاشت زمان تولید پیام به آفست برای جستوجوی زمانی |
leader-epoch-checkpoint | ذخیره تاریخچه تغییر لیدر برای هماهنگی کنترلرها |
نمونه:
users-0/
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.log
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.index
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.timeindex
└── leader-epoch-checkpoint
هر فایل .log در واقع یک سگمنت از لاگ پارتیشن است.
Kafka پیامها را فقط به انتهای لاگ اضافه میکند (append-only) و هرگز رکوردی را بازنویسی نمیکند.
وقتی اندازهی یک سگمنت از مقدار تعیینشده (log.segment.bytes) فراتر رفت، Kafka فایل جدیدی میسازد که نام آن بر اساس base offset رکورد اول در آن سگمنت است:
users-0/
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.log → offsets [0 … ۹۹۹]
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۱۰۰۰.log → offsets [1000 … ۱۹۹۹]
├── ۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۲۰۰۰.log → offsets [2000 … ۲۹۹۹]
به این ترتیب Kafka دادهها را بهصورت ترتیبی، ماژولار و بسیار سریع روی دیسک نگه میدارد.
برای مشاهدهی فایلها کافی است از سیستمعامل میزبان، محتوای دایرکتوریها را بررسی کنید:
ls -lh ./kafka-data/users-0
و خواهید دید:
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.log
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.index
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰.timeindex
leader-epoch-checkpoint
اگر مدتی پیام تولید کنید، فایلهای .log بیشتری ظاهر میشوند (هر ۱ مگابایت یک فایل جدید).
برای مشاهدهی جزئیات داخل یک فایل .log میتوانید از ابزار داخلی Kafka استفاده کنید:
docker exec -it kafka-1 \
kafka-run-class.sh kafka.tools.DumpLogSegments \
--files /var/lib/kafka/data/users-0/00000000000000000000.log \
--print-data-log
این دستور محتوای فایل را همراه با اطلاعات زیر نمایش میدهد:
نمونه خروجی:
offset: 0 position: 0 CreateTime: 1760242021480 keysize: 36 valuesize: 219
key: 2a74853c-319a-4fb0-8da2-4250cb0f71d9
payload: {"user_id": "...", "name": "...", ...}
به این ترتیب میتوانید دقیقاً ببینید که Kafka پیامها را چگونه در فایلها ذخیره کرده است.
برای اجرای ابزارها و دستورات خط فرمان Kafka (مثل kafka-topics.sh, kafka-console-producer.sh, kafka-run-class.sh و غیره)، لازم است ابتدا وارد نود Kafka در محیط Docker شوید و سپس به پوشهی bin بروید.
اگر از Docker Desktop یا خط فرمان استفاده میکنید، مراحل زیر را انجام دهید:
# مشاهده لیست کانتینرها
docker ps
# ورود به کانتینر Kafka (مثلاً kafka-node یا kafka-1)
docker exec -it kafka-node /bin/bash
# رفتن به پوشه ابزارها
cd /opt/kafka/bin
حالا تمام دستورات Kafka را باید با پیشوند ./ اجرا کنید، مثلاً:
./kafka-topics.sh --list --bootstrap-server localhost:9092
./kafka-console-consumer.sh --topic users --from-beginning --bootstrap-server localhost:9092
🔹 یادتان باشد:
اگر ./ را در ابتدای دستور نیاورید، سیستم آن فایل اجرایی را پیدا نمیکند و با خطایcommand not found
روبهرو میشوید.
| مفهوم | توضیح |
|---|---|
| Partition | فایل لاگ ترتیبی برای ذخیره پیامها |
| Segment | بخش فیزیکی از لاگ که دادهها در آن نوشته میشوند |
| Index / Timeindex | نگاشت آفستها و زمانها برای دسترسی سریع |
| Retention & Rotation | تعیین طول عمر و اندازه سگمنتها |
| DumpLogSegments | ابزار بررسی درونی ساختار فایلهای لاگ |
| Mount Volume | روشی ساده برای مشاهده فایلها از میزبان |