Banka ölçeğindeki detaylı veri boru hattımızı (data pipeline) inceleyelim. Teknolojileri görmek için üzerine gelin, detaylara atlamak için tıklayın.
Bir müşteri yüksek tutarlı bir kredi başvurusunda bulunur. Riski değerlendirmek için birçok veriyi (limit, CRM verileri, kredi notu vb.) eş zamanlı olarak bir araya getirdiğimiz bir senaryo düşünelim.
Ana Bankacılık (Core Ledger)
CRM Müşteri Profilleri
Kredi Notu
-- Oracle Tabloları
CREATE TABLE core.accounts (
account_id VARCHAR2(20) PRIMARY KEY,
customer_id VARCHAR2(20),
current_balance NUMBER(15,2)
);
-- Sonuç: { account_id: "1098234", balance: 14500.00 }
-- Operasyonel CRM
SELECT customer_id, risk_segment, kyc_status
FROM crm.customers
WHERE customer_id = '1098234';
-- Sonuç: { risk_segment: "Low", kyc_status: "Verified" }
Müşterilerin dış kurumlardan gelen kredi bürosu raporları, risk faktörleri ve geçmiş davranışları sabit bir tablo yapısına uymaz. Hiyerarşik ve esnek JSON belgelerini (Kredi Notu profillerini) depolamak için MongoDB idealdir.
// Müşteri Kredi Risk Profili
{
"_id": ObjectId("65d8a9e1..."),
"customer_id": "C05T0912",
"credit_score": {
"score": 792,
"score_band": "Excellent",
"reports": [
{"provider": "Equifax", "score": 789},
{"provider": "TransUnion", "score": 795}
]
},
"risk_factors": ["late_payment_2022", "high_utilization"]
}
Bu işlemleri, ana (core) sistemlerde hiçbir performans kaybına neden olmadan anında çekiyoruz.
Olay Akışı (Event Streaming) & CDC
Oracle veritabanını her 5 dakikada bir sorgularsak, canlı müşteriler için performansı düşürürüz. REST API kullanırsak, alıcı sunucu çöktüğünde veriler kaybolur.
Debezium, veritabanı işlem günlüklerini (transaction logs) sessizce okur (sıfır performans kaybı) ve olayları tüketilene kadar Kafka içinde değiştirilemez bir şekilde saklar. Analitik yükü üretim (production) sistemlerinden kusursuz bir şekilde ayırır.
{
"name": "oracle-core-connector",
"config": {
"connector.class": "io.debezium.connector.oracle.OracleConnector",
"database.hostname": "exadata.internal.bank.com",
"database.dbname": "COREDB",
"table.include.list": "core.accounts",
"topic.prefix": "core_tx"
}
}
Sıkı BDDK bankacılık düzenlemeleri nedeniyle, tüm veriler kendi veri merkezimizde (on-premise) kalmalıdır. AWS vb. bulut çözümleri kullanılamaz.
Kurum İçi Nesne Depolama (Object Storage)
Petabaytlarca veri için geleneksel depolama yöntemlerini kullanmak maliyet açısından imkansızdır. Kurum içi Nesne Depolama (MinIO), ucuz ve standart donanımlar üzerinde yatay olarak ölçeklenebilen, S3 uyumlu bir API sunar.
Depolama alanımızı (storage) işlem gücümüzden (compute) tamamen ayırarak, ham JSON, Parquet ve Ses dosyalarını yerel formatlarında depolamamızı sağlar.
Müşteri 360 görünümünü oluşturmak için milyarlarca geçmiş olayı işliyoruz.
Dağıtık Hesaplama (Distributed Compute)
Pandas, verileri tamamen tek bir makinenin RAM'ine yükler. 500GB'lık geçmiş bankacılık verilerini Pandas'ta birleştirmeye (join) çalışırsanız, "Out of Memory (OOM)" hatası verir ve çöker.
Spark, bu birleştirme işlemini OpenShift (Kubernetes) kümemizdeki 50 düğüme (node) dağıtır. Grafı "tembel (lazy)" bir şekilde değerlendirir ve yalnızca gerektiğinde diske yazarak Terabaytlarca veriyi sorunsuz bir şekilde işler.
# MinIO'dan dağıtık veri akışlarını yükle
tx_df = spark.read.format("delta").load("s3a://datalake/silver/transactions")
click_df = spark.read.format("delta").load("s3a://datalake/silver/clicks")
# Milyarlarca satır üzerinden Müşteri ID ile Dağıtık Birleştirme (Join)
c360_df = tx_df.join(click_df, "customer_id")
# Ana katmana yaz
c360_df.write.format("delta").save("s3a://datalake/gold/customer_360")
✅ [Job 1] Completed in 12.4s.
> 15.4M rows written to s3a://datalake/gold/customer_360
Borunun (pipeline) uçtan uca çalışmasını düzenleyen ve izleyen bir beyine ihtiyacımız var.
İş Akışı (Workflow) Orkestrasyonu
Basit "cron" betikleri, bir görev hata verdiğinde bunu diğerlerine bildirmez. "Müşteri verisi oluşturulmadan ML modelini çalıştırma" gibi karmaşık bağımlılıkları yönetemezler.
Airflow, görevleri bir DAG (Directed Acyclic Graph) olarak kodla tanımlamanıza olanak tanır. Herhangi bir Spark görevi çökerse, Airflow durumu yakalar, uyarır ve yalnızca başarısız olan adımları yeniden dener.
from airflow import DAG
from airflow.providers.apache.spark.operators.spark_submit import SparkSubmitOperator
with DAG('credit_risk_pipeline', schedule_interval='@daily') as dag:
run_spark_job = SparkSubmitOperator(
task_id='build_customer_360',
application='/jobs/customer_360.py',
conn_id='spark_default'
)
# Bağımlılık Zinciri
wait_for_data >> run_spark_job >> run_data_quality_tests
Hatalı verilerin (örn. negatif hesap bakiyesi) risk modellerimize girmesini engellemeliyiz.
Otomatik Veri Doğrulama (Validation)
Yazılımcılar kodlarını yayına almadan önce nasıl birim (unit) testleri yazıyorsa, Veri Mühendisleri de verileri için test yazmalıdır.
Great Expectations, verinin beklenen şemaya ve iş kurallarına uyduğunu matematiksel olarak test eder (örn. "Hesap bakiyesi hiçbir zaman NULL olmamalıdır"). Test başarısız olursa, Airflow veri akışını durdurur ve hatalı model üretilmesini engeller.
{
"expectation_type": "expect_column_values_to_not_be_null",
"kwargs": {
"column": "current_balance"
},
"meta": {
"notes": "Hesap bakiyesi kritik bir değişkendir, kesinlikle dolu olmalıdır."
}
}
Ham 360 verisini, temiz ve test edilebilir bir Kredi Risk modeline dönüştürüyoruz.
SQL için Yazılım Mühendisliği
Stored procedures, teknoloji bağımlılığına (vendor lock-in), imkansız hata ayıklamaya ve sürüm kontrolünün (version control) olmamasına neden oldu.
dbt, SQL'i bir yazılım gibi ele alır: git entegrasyonu, DRY (Don't Repeat Yourself) makroları ve derlenmiş bir DAG (bağımlılık grafiği) elde edersiniz; böylece tabloların tam olarak hangi sırayla oluşturulması gerektiğini bilirsiniz.
SELECT
c.customer_id,
c.risk_segment,
c360.total_balance,
CASE
WHEN c360.total_balance < 500 AND c.risk_segment = 'High'
THEN 'DECLINE_LOAN' ELSE 'APPROVE'
END as loan_decision
FROM {{ source('postgres', 'customers') }} c
JOIN {{ ref('stg_customer_360') }} c360 ON c.customer_id = c360.customer_id
Veri Bilimciler, MinIO ve Oracle genelinde nihai modelleri sorunsuz bir şekilde sorgular.
Federe Sorgu Motoru (Federated Query Engine)
Normalde, sonlandırılmış veriyi salt sorgulayabilmek için Veri Gölü'nden (Data Lake) alıp bir Veri Ambarına (Teradata gibi) taşımak için bir ETL (Extract, Transform, Load) işi yazmanız gerekirdi.
Trino bu adımı atlar. Analistlerin, MinIO'daki ham Parquet dosyalarını doğrudan Oracle'daki canlı operasyonel tablolarla anında birleştiren SQL yazmalarına olanak tanır. Hiçbir veri taşıma (Zero ETL) gerektirmez.
-- Canlı Oracle ve MinIO Delta Lake'i birleştiren Trino sorgusu
SELECT risk.loan_decision, COUNT(*)
FROM oracle.core.accounts AS core
JOIN minio.gold.fct_credit_risk AS risk
ON core.customer_id = risk.customer_id
WHERE core.account_status = 'ACTIVE'
GROUP BY 1;
| loan_decision | count |
|---|---|
| APPROVE | 1,204,591 |
| DECLINE_LOAN | 3,042 |
> Query 20260818_trino
> 100 worker nodes üzerinde 0.8 saniyede tamamlandı.
Bu mimariyi sıradan bir pipeline'dan "Banka Ölçeğinde (Enterprise)" bir sisteme dönüştüren temel taş: Güvenlik Düzlemi (Security Plane).
SASL/GSSAPI Merkezi Kimlik Doğrulama
Bir banka ortamında, Spark'ın Kafka'dan veri okuması veya Trino'nun MinIO'ya erişmesi sadece kullanıcı adı/şifre ile yapılamaz. Veriler ağ üzerinde şifrelenmeli ve servisler birbirlerini doğrulamalıdır.
Kerberos mimarimizde bir adım değil, tüm adımları kapsayan bir şemsiyedir. Her servis (Kafka Broker, Spark Executor, Trino Worker) iletişime geçmeden önce KDC (Key Distribution Center) sunucusundan bir bilet (Ticket Granting Ticket - TGT) alır ve bu biletle kriptografik olarak güvenli konuşur.
// Kafka Client SASL/GSSAPI Configuration
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/etc/security/keytabs/spark-executor.service.keytab"
storeKey=true
useTicketCache=false
principal="spark/node12@BANK.CORP";
};
> $ kinit -kt /etc/security/keytabs/user.keytab data_engineer@BANK.CORP
> Authenticated to Kerberos v5. (Encryption: aes256-cts-hmac-sha1-96)