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
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;
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.")
Bu konuda ne bulacaksınız?
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?
[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]

id", val)
Redis Komutları (Lua’dan)
Pratik Uyumlama Rehberi