Bvural41 1
Bvural41
kralhakan2009 1
kralhakan2009
noisiv 1
noisiv
Manwe Work 1
Manwe Work
Vahsi Uzman 1
Vahsi Uzman
Cannn6161 1
Cannn6161
B 1
berione65
sen272 1
sen272
Mt2Hizmet 1
Mt2Hizmet
Hikaye Ekle
Reklam vermek için turkmmo@gmail.com
Kaynak ikonu

QF yerine Redis kullanmak 2025-07-07

indirmek için izniniz yok
  • Konuyu başlatan Konuyu başlatan mistikaptal
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 13
  • Görüntüleme Görüntüleme 1K
5.00 yıldız(lar) 2 Değerlendirme Değerlendirenler

mistikaptal

Mysteriously Stupidity
TM Üye
Katılım
8 Haz 2024
Konular
85
Mesajlar
526
Online süresi
2mo 12d
Reaksiyon Skoru
407
Altın Konu
0
Başarım Puanı
121
MmoLira
3,278
DevLira
189
Ticaret - 0%
0   0   0

ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!



Bu konuda redis veritabanına mantıksal olarak yani pratikte nasıl geçileceğini anlatacağım, yanlış anlaşılma olmaması adına bazı şeyleri düzeltmek zorundayım, yani tamamen bir geçiş işlemi içermemektedir.

Neden Redis?

📦 MySQL (veya MariaDB)


  • Kalıcı veriler tutulur:
    • shop_item
    • karakter bilgileri
    • eşya bilgileri
    • fiyatlar, vnumlar, moblar, vs.
  • Oyuncu oyundan çıksa bile veriler kaybolmaz.

⚡

  • Geçici/verimli erişim gereken şeylerde kullanılır (qf gibi):
    • cooldown’lar
    • aktif GM komutları
    • hızlı sayaçlar
Quest FlagRedis Karşılığı
pc.setf("x","y",val)redis.set("x:y:pid", val)
pc.getf("x","y")redis.get("x:y:pid")
KalıcıGeçici (expire ile süreli)
Yavaş (disk)Hızlı (RAM)

MySQL ve Redis birlikte sorunsuz, performanslı ve güvenli şekilde kullanılabilir.

Sunucu açılırken Redis’e SQL'den preload yapılır

Shop kapandığında veya belli aralıkla Redis → SQL sync yapılır.

Örnek olarak ikisinin de nasıl kullanıldığını altta bulacaksanız;

🧠 Redis Komutları (Lua’dan)​


KomutAçıklama
redis.set(key, value)Basit veri yazma
redis.get(key)Veri okuma
redis.exists(key)Var mı kontrol
redis.setex(key, saniye, val)Zamanlı set (örnek: cooldown)
redis.ttl(key)Ne kadar süresi kaldı (cooldown göstermek için)
redis.incr(key)Sayaç +1
redis.del(key)Silme

Questflag:

[CODE title="QF"]
-- Oyuncunun günlük giriş bonusunu alıp almadığını kontrol ediyorsun
if pc.getf("login_reward", "taken") == 1 then
return
end
pc.setf("login_reward", "taken", 1)[/CODE]

Questflag yerine Redis kullanacak olursak:


[CODE title="Redis"]
local key = string.format("reward:daily:%d", pc.get_player_id())
if redis.exists(key) then
return
end
redis.setex(key, 86400, 1) -- 1 gün geçerli[/CODE]

Bir başka örnek ile daha açıklamaya çalışalım;

Bekleme süresi olayı (eski hali)

C++:
if get_global_time() < pc.getf("teleport", "cooldown") then
    syschat("Bekleme süresi var.")
    return
end
pc.setf("teleport", "cooldown", get_global_time() + 30)

Redis (yeni hali)

C++:
local key = string.format("teleport_cd:%d", pc.get_player_id())
local ttl = redis.ttl(key)

if ttl > 0 then
    syschat(string.format("Bekleme süresi var: %d sn", ttl))
    return
end

redis.setex(key, 30, 1)
syschat("Teleport edildin.")

💡 Pratik Uyumlama Rehberi​


Ne yapmak istiyorsun?Quest FlagRedis Karşılığı
Günlük ödül alındı mı?getf/setfredis.exists, setex
NPC sınırı var mı?getf(...) > 10redis.incr, ttl ile sınırlama
Günlük sıfırlanmacron + SQLRedis expire ile otomatik
Teleport süresigetf("cd")redis.ttl(key)

Bu konuda ne bulacaksınız?

Redis erişimi için get/set yardımcıları içeren yeni bir RedisManager sınıfını,
Bağlantıları ve komutları işlemek için hiredis kullanan temel bir Redis istemcisi ekleme örneğini,
Redis bağlantılarını ve işlemlerini desteklemek için DBManager nasıl güncellenir ve sunucu başlatma rutinine bağlama mantığını,
Veritabanı sunucusunun Makefile'ı derleme sırasında tanıtabilmek için yeni Redis kütüphanesini,
redis-plus-plus (sw::redis++) sunucu koduna dahil nasıl edilir (örnek kullanımını),
Lua’dan Çağırabilmek için gerekli olan (Lua binding / wrapper) örneğini,

Eğer doğrudan Lua'da redis.get() gibi fonksiyonlar kullanmak istiyorsan, bu sw::redis++ fonksiyonlarını (kendi C++ kaynak koduna tanıtman, Lua binding yapman) gerekir. Bu sayede kendi oyununa Lua'da kullanabilmek için bu fonksiyonları açmış olacaksın!
redis_lua_bindings.cpp


C++:
#include "stdafx.h"
#include <lua.hpp>
#include <string>
#include <sw/redis++/redis++.h>

using namespace sw::redis;

static std::shared_ptr<Redis> g_redis;

void InitRedisConnection() {
    if (!g_redis) {
        try {
            g_redis = std::make_shared<Redis>("tcp://127.0.0.1:6379");
        } catch (const std::exception& e) {
            sys_err("Redis connection failed: %s", e.what());
        }
    }
}

// redis.set(key, value)
int lua_redis_set(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);
    const char* value = luaL_checkstring(L, 2);

    InitRedisConnection();
    g_redis->set(key, value);

    return 0;
}

// redis.setex(key, seconds, value)
int lua_redis_setex(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);
    int seconds = luaL_checkinteger(L, 2);
    const char* value = luaL_checkstring(L, 3);

    InitRedisConnection();
    g_redis->setex(key, std::chrono::seconds(seconds), value);

    return 0;
}

// redis.get(key)
int lua_redis_get(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);

    InitRedisConnection();
    auto val = g_redis->get(key);

    if (val) {
        lua_pushstring(L, val->c_str());
    } else {
        lua_pushnil(L);
    }

    return 1;
}

// redis.exists(key)
int lua_redis_exists(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);

    InitRedisConnection();
    bool exists = g_redis->exists(key) > 0;

    lua_pushboolean(L, exists);
    return 1;
}

// redis.del(key)
int lua_redis_del(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);

    InitRedisConnection();
    g_redis->del(key);

    return 0;
}

// redis.ttl(key)
int lua_redis_ttl(lua_State* L) {
    const char* key = luaL_checkstring(L, 1);

    InitRedisConnection();
    auto ttl = g_redis->ttl(key);

    if (ttl) {
        lua_pushinteger(L, static_cast<int>(ttl->count()));
    } else {
        lua_pushinteger(L, -1); // -1 = sonsuz
    }

    return 1;
}

// Kayıt
void RegisterRedisFunctions(lua_State* L) {
    lua_getglobal(L, "redis");
    if (lua_isnil(L, -1)) {
        lua_newtable(L);
        lua_setglobal(L, "redis");
    }

    lua_getglobal(L, "redis");

    lua_pushcfunction(L, lua_redis_set);
    lua_setfield(L, -2, "set");

    lua_pushcfunction(L, lua_redis_setex);
    lua_setfield(L, -2, "setex");

    lua_pushcfunction(L, lua_redis_get);
    lua_setfield(L, -2, "get");

    lua_pushcfunction(L, lua_redis_exists);
    lua_setfield(L, -2, "exists");

    lua_pushcfunction(L, lua_redis_del);
    lua_setfield(L, -2, "del");

    lua_pushcfunction(L, lua_redis_ttl);
    lua_setfield(L, -2, "ttl");

    lua_pop(L, 1);
}

Nasıl Çağıracaksın?

C++:
// questlua.cpp içinde lua_init fonksiyonunun en altına ekle:

RegisterRedisFunctions(L);

ve dahil et

extern void RegisterRedisFunctions(lua_State* L);

[CODE lang="rich" title="Kullanım Örneği"]local key = string.format("cd:move:%d", pc.get_player_id())
if redis.exists(key) then
local kalan = redis.ttl(key)
syschat("Bekleme süresi var: "..kalan.." sn")
return
end

redis.setex(key, 30, "1")
syschat("Işınlandın.")
[/CODE]


 

Ekli dosyalar

Son düzenleme:

En Çok Reaksiyon Alan Mesajlar

Konunun neden oluştuğunu düşünürsek db iletişimini düşürmek yada modüler bir yapı ihtiyacı olabilir gördüğüm kadarıyla ama gereklilik konusu şüpheli belki quest, affect tablolarında kullanılabilir tek olasılık o, sql üzerinden çalışıyor ve cache yazılmamışsa gerekliliği var c++ üzerinde yazılmış bir kod yada cache daha yüksek performans verecektir.

Bu yüzden redis kullanım gerekliliğini tam açıklamak gerekli konunun eksiği bu şu an, sadece quest flag ve veritabanı olmaz bunlar için tamamen gereksiz. Sıfırdan farklı bir oyun geliştiriliyor ise o zaman evet gerek duyulur.
Hobaa eline sağlık, araştırmalarını beğenerek takip ediyorum fakat atlanmaması gereken 1 konu:

Redis defaultta persistent storage değil, memoryde tutuluyor, bu yüzden instance kill edildiğinde yazılan bütün qf'ler de gider, db'ye yazılmış gibi bir sonraki restartta bilgiler devam etmez.

Redis'in persistance için 2 seçeneği var, snapshotting yada AOF, snapshot kullanıldığında da snapshot -> crash aralığındaki data kayboluyor, bu yüzden append only file (write ahead log gibi bir yapısı var) ile persist etmek daha sağlıklı.

Ama bunu yapınca da açıkçası herhangi bir databaseden pek bir farkı kalmıyor. Hali hazırda modern database teknolojileri zaten sık erişilen tabloları memory'de tutuyor, yazma işlemleri için ise hali hazırda WAL yapısı çoğu database de mevcut. (LSM ve SSTable hakkında bilgiler için aşağıdaki video iyi bir özet niteliğinde: Öğeyi görmek için üye olmalısınız.)

Paylaşım için teşekkürler, distributed cache konusu için redis değerlendirilebilir belki farklı sunucularda game run eden arkadaşlarımız var ise.

Edit: Distributed cache'den bahsettikten sonra Upstash'den bahsetmesek olmazdı, kurucusu türk, redis as a service (ve bunun dışında farklı şeyler de var) hizmeti veriyorlar, konuyla ilgilenenlere aşağıdaki videoda anlatımı mevcut dinlemenizi tavsiye ederim:

Öğeyi görmek için üye olmalısınız.
Eline sağlık, uygulama için teşekkürler! Ancak bu yaklaşımın performans açısından beklenen avantajları tam olarak sağladığını düşünmüyorum. Yanlış hatırlamıyorsam, setflag zaten bellekte map yapısıyla tutuluyor ve hızlı erişim sağlıyor. Redis’e geçmek, yalnızca game proccessler arasında senkronizasyon sağlayacaktır. Eğer hedef buysa, bu mantıklı bir seçim olabilir, ancak çoğu durumda network üzerinden Redis’e erişim, yerel bellek kullanımına kıyasla ek yük getirebilir.Bence daha verimli bir yaklaşım, Redis’i game'e entegre etmek yerine db'ye önbellek olarak kullanmak olurdu. Örneğin, sık sorgulanan verileri Redis’te tutarak MySQL’e olan yükü azaltabiliriz. Redis’in kendi persistence özelliklerinden (RDB veya AOF) faydalanmak veri kaybını önlemek için daha pratik olabilir. Bu sayede hem performans artar hem de veri tutarlılığı sağlanır.

Redis ile mesela anlık güncellenen oyun içi sıralama yapılabilir. Veritabanına giden doğruluğu hayati öneme sahip olmayan şeyler de tutulabilir. Bunlar da farklı uygulama önerilerim.
Hobaa eline sağlık, araştırmalarını beğenerek takip ediyorum fakat atlanmaması gereken 1 konu:

Redis defaultta persistent storage değil, memoryde tutuluyor, bu yüzden instance kill edildiğinde yazılan bütün qf'ler de gider, db'ye yazılmış gibi bir sonraki restartta bilgiler devam etmez.

Redis'in persistance için 2 seçeneği var, snapshotting yada AOF, snapshot kullanıldığında da snapshot -> crash aralığındaki data kayboluyor, bu yüzden append only file (write ahead log gibi bir yapısı var) ile persist etmek daha sağlıklı.

Ama bunu yapınca da açıkçası herhangi bir databaseden pek bir farkı kalmıyor. Hali hazırda modern database teknolojileri zaten sık erişilen tabloları memory'de tutuyor, yazma işlemleri için ise hali hazırda WAL yapısı çoğu database de mevcut. (LSM ve SSTable hakkında bilgiler için aşağıdaki video iyi bir özet niteliğinde: Öğeyi görmek için üye olmalısınız.)

Paylaşım için teşekkürler, distributed cache konusu için redis değerlendirilebilir belki farklı sunucularda game run eden arkadaşlarımız var ise.

Edit: Distributed cache'den bahsettikten sonra Upstash'den bahsetmesek olmazdı, kurucusu türk, redis as a service (ve bunun dışında farklı şeyler de var) hizmeti veriyorlar, konuyla ilgilenenlere aşağıdaki videoda anlatımı mevcut dinlemenizi tavsiye ederim:

Öğeyi görmek için üye olmalısınız.
redisin persistence konusu özellikle snapshot ile aof arasındaki farkları ve append-only filein veri güvenliği açısından önemini bu kadar net özetlemen çok iyi oldu. aslında bu konuyada değinmeyi düşünmüştüm ama o anki odak biraz farklıydı :D senin bu detaylı anlatımın tam da yerinde oldu :) upstash önerisi için de şöyle söyleyeyim daha önce denk gelmiştim ama bu video üzerinden bir bakacağım mutlaka, özellikle Redis as a Service tarafının ve multi tenant kullanım senaryoları ciddi avantaj sağlayabiliyor.
Hobaa eline sağlık, araştırmalarını beğenerek takip ediyorum fakat atlanmaması gereken 1 konu:

Redis defaultta persistent storage değil, memoryde tutuluyor, bu yüzden instance kill edildiğinde yazılan bütün qf'ler de gider, db'ye yazılmış gibi bir sonraki restartta bilgiler devam etmez.

Redis'in persistance için 2 seçeneği var, snapshotting yada AOF, snapshot kullanıldığında da snapshot -> crash aralığındaki data kayboluyor, bu yüzden append only file (write ahead log gibi bir yapısı var) ile persist etmek daha sağlıklı.

Ama bunu yapınca da açıkçası herhangi bir databaseden pek bir farkı kalmıyor. Hali hazırda modern database teknolojileri zaten sık erişilen tabloları memory'de tutuyor, yazma işlemleri için ise hali hazırda WAL yapısı çoğu database de mevcut. (LSM ve SSTable hakkında bilgiler için aşağıdaki video iyi bir özet niteliğinde: )

Paylaşım için teşekkürler, distributed cache konusu için redis değerlendirilebilir belki farklı sunucularda game run eden arkadaşlarımız var ise.

Edit: Distributed cache'den bahsettikten sonra Upstash'den bahsetmesek olmazdı, kurucusu türk, redis as a service (ve bunun dışında farklı şeyler de var) hizmeti veriyorlar, konuyla ilgilenenlere aşağıdaki videoda anlatımı mevcut dinlemenizi tavsiye ederim:

 
Son düzenleme:
Hobaa eline sağlık, araştırmalarını beğenerek takip ediyorum fakat atlanmaması gereken 1 konu:

Redis defaultta persistent storage değil, memoryde tutuluyor, bu yüzden instance kill edildiğinde yazılan bütün qf'ler de gider, db'ye yazılmış gibi bir sonraki restartta bilgiler devam etmez.

Redis'in persistance için 2 seçeneği var, snapshotting yada AOF, snapshot kullanıldığında da snapshot -> crash aralığındaki data kayboluyor, bu yüzden append only file (write ahead log gibi bir yapısı var) ile persist etmek daha sağlıklı.

Ama bunu yapınca da açıkçası herhangi bir databaseden pek bir farkı kalmıyor. Hali hazırda modern database teknolojileri zaten sık erişilen tabloları memory'de tutuyor, yazma işlemleri için ise hali hazırda WAL yapısı çoğu database de mevcut. (LSM ve SSTable hakkında bilgiler için aşağıdaki video iyi bir özet niteliğinde: )

Paylaşım için teşekkürler, distributed cache konusu için redis değerlendirilebilir belki farklı sunucularda game run eden arkadaşlarımız var ise.

Edit: Distributed cache'den bahsettikten sonra Upstash'den bahsetmesek olmazdı, kurucusu türk, redis as a service (ve bunun dışında farklı şeyler de var) hizmeti veriyorlar, konuyla ilgilenenlere aşağıdaki videoda anlatımı mevcut dinlemenizi tavsiye ederim:


redisin persistence konusu özellikle snapshot ile aof arasındaki farkları ve append-only filein veri güvenliği açısından önemini bu kadar net özetlemen çok iyi oldu. aslında bu konuyada değinmeyi düşünmüştüm ama o anki odak biraz farklıydı :D senin bu detaylı anlatımın tam da yerinde oldu :) upstash önerisi için de şöyle söyleyeyim daha önce denk gelmiştim ama bu video üzerinden bir bakacağım mutlaka, özellikle Redis as a Service tarafının ve multi tenant kullanım senaryoları ciddi avantaj sağlayabiliyor.
 
Forumda böyle şeyleri konuşuyor olmak bence çok güzel. Elinize sağlık.
 
Konunun neden oluştuğunu düşünürsek db iletişimini düşürmek yada modüler bir yapı ihtiyacı olabilir gördüğüm kadarıyla ama gereklilik konusu şüpheli belki quest, affect tablolarında kullanılabilir tek olasılık o, sql üzerinden çalışıyor ve cache yazılmamışsa gerekliliği var c++ üzerinde yazılmış bir kod yada cache daha yüksek performans verecektir.

Bu yüzden redis kullanım gerekliliğini tam açıklamak gerekli konunun eksiği bu şu an, sadece quest flag ve veritabanı olmaz bunlar için tamamen gereksiz. Sıfırdan farklı bir oyun geliştiriliyor ise o zaman evet gerek duyulur.
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst