Fethi Polat 1
Fethi Polat
xranzei 1
xranzei
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


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.

⚡ Redis

  • 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]


Yazar
DonuminikToretto
Kaynak İndirilme
5
Görüntüleme
113
İlk yayınlama
Son Güncelleme

Ratings

0.00 yıldız(lar) 0 rating
Geri
Üst