ET框架应用
本来我都已经Redis我都快融合完了,然后在群里讨论了下Redis对游戏项目的帮助,结果得到的反馈是完全没必要。
按猫大的说法就是,用户在运行时,数据已经保存在内存中了,再加一层Redis就是多此一举,还浪费性能。
所以新的解决方案就是,给用户添加一个数据持久化组件,组件定时将用户的数据存储到数据库中,关键数据变动直接存储到数据库,以此来替代Redis。【主要还是从减轻数据库读写负担的角度出发】
什么,你说容灾,普通数据直接给用户补偿,关键数据直接保存都丢失了,换Redis能好到哪里去。
Redis融合流程
虽然做了无用功,但是简单的记录还是要记录下的。
在服务端 NuGet 中搜索 StackExchange.Redis,直接点击按钮安装
在服务端Model层添加脚本RedisComponent
using StackExchange.Redis;
namespace ETModel
{
public class RedisComponent : Component
{
public ConnectionMultiplexer m_Redis;
public IDatabase m_RedisDB;
public IServer m_RedisServer;
}
}
在服务端Hotfix层添加脚本RedisComponentSystem
using ETModel;
using StackExchange.Redis;
using System;
using System.Threading;
namespace ETHotfix
{
[ObjectSystem]
public class RedisComponentAwakeSystem : AwakeSystem<RedisComponent>
{
public override void Awake(RedisComponent self)
{
self.Awake();
}
}
[ObjectSystem]
public class RedisComponentUpdateSystem : UpdateSystem<RedisComponent>
{
long time = TimeHelper.ClientNow();
long nowtime;
public override void Update(RedisComponent self)
{
long nowtime = TimeHelper.ClientNow();
//超过十秒保存一次数据到数据库
if (nowtime - time > 10000)
{
self.SaveRedis().Coroutine();
time = nowtime;
}
}
}
public static class RedisComponentSystem
{
public static void Awake(this RedisComponent self)
{
self.m_Redis = ConnectionMultiplexer.Connect("localhost");
self.m_RedisDB = self.m_Redis.GetDatabase(0);
self.m_RedisServer = self.m_Redis.GetServer("localhost:6379,password=password");
}
/// <summary>
/// 存类,key只能是数据库主键值
/// </summary>
/// <param name="key"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static bool SetClass<T>(this RedisComponent self, T component) where T : ComponentWithId
{
return self.SetString(component.GetType().Name, component.Id.ToString(), MongoHelper.ToBson(component));
}
/// <summary>
/// 取类,key只能是数据库主键值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="self"></param>
/// <param name="key"></param>
/// <returns></returns>
public static async ETTask<T> GetClass<T>(this RedisComponent self, long Id) where T : ComponentWithId
{
RedisValue redisValue = self.GetString(typeof(T).Name, Id.ToString());
if (redisValue.HasValue)
{
return MongoHelper.FromBson<T>(redisValue);
}
else
{
T t = await QueryComponent<T>(Id);
if (t != null)
{
self.SetClass(t);
}
return t;
}
}
public static async ETTask<T> QueryComponent<T>(long Id) where T : ComponentWithId
{
DBProxyComponent dBProxyComponent = Game.Scene.GetComponent<DBProxyComponent>();
return await dBProxyComponent.Query<T>(Id);
}
/// <summary>
/// 存字符串
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool SetString(this RedisComponent self, RedisKey key, RedisValue field, RedisValue value)
{
try
{
self.m_RedisDB.HashSet(key, field, value);
return true;
}
catch (Exception ex)
{
Log.Error("Redis数据写入错误" + ex.ToString());
return false;
}
}
/// <summary>
/// 取字符串
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static RedisValue GetString(this RedisComponent self, RedisKey key, RedisValue field)
{
return self.m_RedisDB.HashGet(key, field);
}
/// <summary>
/// 存储数据到数据库里
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static async ETVoid SaveRedis(this RedisComponent self)
{
//获取库中所有的Key
var keys = self.m_RedisServer.Keys();
foreach (var key in keys)
{
//获取当前key下所有的field
RedisValue[] fields = self.m_RedisDB.HashValues(key);
ComponentWithId componentWithId = MongoHelper.FromBson<ComponentWithId>(key);
await SaveComponent(componentWithId);
}
}
public static async ETTask SaveComponent<T>(T component) where T : ComponentWithId
{
DBProxyComponent dBProxyComponent = Game.Scene.GetComponent<DBProxyComponent>();
await dBProxyComponent.Save(component);
}
/// <summary>
/// 示范
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="self"></param>
/// <param name="userId"></param>
/// <param name="component"></param>
public static void SetHash<T>(this RedisComponent self, long Id, T component) where T : ComponentWithId
{
//组件类型名
string key = component.GetType().Name;
//组件Id
string field = Id.ToString();
//组件
byte[] value = MongoHelper.ToBson(component);
//写入组件
self.m_RedisDB.HashSet(key, field, value);
//读取某个类型的所有组件
RedisValue[] components = self.m_RedisDB.HashKeys(key);
//读取单个组件
T newComponent = self.m_RedisDB.HashGet(key, field) as T;
//删除用户数据
self.m_RedisDB.HashDelete(typeof(T).Name, Id);
//获取库中所有的组件
var keys = self.m_RedisServer.Keys();
}
}
}