mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-08-08 22:26:17 +00:00
perf[orm]: 去掉IEntityCaches多余的接口
This commit is contained in:
@@ -63,13 +63,18 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class OrmManager implements IOrmManager {
|
||||
|
||||
private static final Map<Class<? extends IEntity<?>>, IEntityCaches<?, ?>> entityCachesMap = new HashMap<>();
|
||||
|
||||
private OrmConfig ormConfig;
|
||||
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase mongodbDatabase;
|
||||
|
||||
/**
|
||||
* 全部的Entity定义,key为对应的class,value为当前的Entity是否在当前项目中以缓存的形式使用
|
||||
*/
|
||||
private final Map<Class<?>, Boolean> allEntityCachesUsableMap = new HashMap<>();
|
||||
|
||||
private final Map<Class<? extends IEntity<?>>, IEntityCaches<?, ?>> entityCachesMap = new HashMap<>();
|
||||
|
||||
private final Map<Class<? extends IEntity<?>>, String> collectionNameMap = new ConcurrentHashMap<>();
|
||||
|
||||
public OrmConfig getOrmConfig() {
|
||||
@@ -87,6 +92,7 @@ public class OrmManager implements IOrmManager {
|
||||
for (var entityDef : entityDefMap.values()) {
|
||||
var entityCaches = new EntityCaches(entityDef);
|
||||
entityCachesMap.put(entityDef.getClazz(), entityCaches);
|
||||
allEntityCachesUsableMap.put(entityDef.getClazz(), false);
|
||||
}
|
||||
|
||||
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
|
||||
@@ -172,6 +178,7 @@ public class OrmManager implements IOrmManager {
|
||||
public void inject() {
|
||||
var applicationContext = OrmContext.getApplicationContext();
|
||||
var beanNames = applicationContext.getBeanDefinitionNames();
|
||||
|
||||
for (var beanName : beanNames) {
|
||||
var bean = applicationContext.getBean(beanName);
|
||||
|
||||
@@ -185,34 +192,37 @@ public class OrmManager implements IOrmManager {
|
||||
}
|
||||
|
||||
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
|
||||
Class<? extends IEntity<?>> clazz = (Class<? extends IEntity<?>>) types[1];
|
||||
IEntityCaches<?, ?> entityCaches = OrmContext.getOrmManager().getEntityCaches(clazz);
|
||||
Class<? extends IEntity<?>> entityClazz = (Class<? extends IEntity<?>>) types[1];
|
||||
IEntityCaches<?, ?> entityCaches = entityCachesMap.get(entityClazz);
|
||||
|
||||
if (entityCaches == null) {
|
||||
throw new RuntimeException(StringUtils.format("实体缓存对象[entityCaches:{}]不存在", clazz));
|
||||
throw new RuntimeException(StringUtils.format("实体缓存对象[entityCaches:{}]不存在", entityClazz));
|
||||
}
|
||||
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
ReflectionUtils.setField(field, bean, entityCaches);
|
||||
entityCaches.setUsable(true);
|
||||
allEntityCachesUsableMap.put(entityClazz, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAfter() {
|
||||
var unusableEntityClassList = entityCachesMap.entrySet().stream()
|
||||
.filter(it -> !it.getValue().isUsable())
|
||||
allEntityCachesUsableMap.entrySet().stream()
|
||||
.filter(it -> !it.getValue())
|
||||
.map(it -> it.getKey())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
unusableEntityClassList.forEach(it -> {
|
||||
entityCachesMap.remove(it);
|
||||
});
|
||||
.forEach(it -> entityCachesMap.remove(it));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends IEntity<?>> IEntityCaches<?, E> getEntityCaches(Class<E> clazz) {
|
||||
var usable = allEntityCachesUsableMap.get(clazz);
|
||||
if (usable == null) {
|
||||
throw new RunException("没有定义[]的EntityCaches,无法获取", clazz.getCanonicalName());
|
||||
}
|
||||
if (!usable) {
|
||||
throw new RunException("Orm没有使用[]的EntityCaches,为了节省内存提前释放了它;只有使用EntityCachesInjection注解的Entity才能被动态获取", clazz.getCanonicalName());
|
||||
}
|
||||
return (IEntityCaches<?, E>) entityCachesMap.get(clazz);
|
||||
}
|
||||
|
||||
@@ -233,7 +243,6 @@ public class OrmManager implements IOrmManager {
|
||||
collectionName = StringUtils.substringBeforeLast(StringUtils.uncapitalize(entityClazz.getSimpleName()), "Entity");
|
||||
collectionNameMap.put(entityClazz, collectionName);
|
||||
}
|
||||
|
||||
return mongodbDatabase.getCollection(collectionName, entityClazz);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,11 +50,9 @@ public class EntityCaches<PK extends Comparable<PK>, E extends IEntity<PK>> impl
|
||||
|
||||
private static final int BATCH_SIZE = 512;
|
||||
|
||||
private EntityDef entityDef;
|
||||
private final EntityDef entityDef;
|
||||
|
||||
private LoadingCache<PK, PNode<E>> cache;
|
||||
|
||||
private boolean usable;
|
||||
private final LoadingCache<PK, PNode<E>> cache;
|
||||
|
||||
public EntityCaches(EntityDef entityDef) {
|
||||
this.entityDef = entityDef;
|
||||
@@ -304,16 +302,6 @@ public class EntityCaches<PK extends Comparable<PK>, E extends IEntity<PK>> impl
|
||||
return cache.estimatedSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsable() {
|
||||
return this.usable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsable(boolean usable) {
|
||||
this.usable = usable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String recordStatus() {
|
||||
var stats = cache.stats();
|
||||
|
||||
@@ -55,10 +55,6 @@ public interface IEntityCaches<PK extends Comparable<PK>, E extends IEntity<PK>>
|
||||
|
||||
long size();
|
||||
|
||||
boolean isUsable();
|
||||
|
||||
void setUsable(boolean usable);
|
||||
|
||||
/**
|
||||
* 统计缓存命中率
|
||||
*/
|
||||
|
||||
@@ -28,11 +28,11 @@ public interface IEntity<PK extends Comparable<PK>> {
|
||||
/**
|
||||
* 一个文档的写入到数据库的version版本,version的get和set方法
|
||||
* <p>
|
||||
* 写入一条数据到数据库的时候会对比以下老的vs和数据库的vs是不是一样,不是一样的话无法写入,一致的话就写入数据并且让vs自增+1.
|
||||
* 主要是为了防止多个服务器去操作同一条数据,保证分布式环境的数据一致性,就是一个数据版本号的简单实现,版本号一致才能写入数据。
|
||||
* 在分布式环境的那种有状态服务器中会遇到,比如网关路由一个玩家的数据到a服务器,这个时候你加了一个b服务器,有可能下一条数据就被路由到b。
|
||||
* 写入一条数据到数据库的时候会对比当前entity的vs和数据库的vs是不是一样,不是一样的话无法写入,一致的话就写入数据并且让vs自增+1.
|
||||
* 主要是为了防止多个服务器去操作同一条数据,保证在分布式环境的数据一致性;简单的说就是一个数据版本号的简单实现,版本号一致才能写入数据。
|
||||
* 在分布式环境中,会存在有状态服务器,比如网关路由一个玩家的数据到a服务器,这个时候你加了一个b服务器,有可能下一条数据就被路由到b。
|
||||
* 虽然用了一致性hash的负载均衡算法,但是一样有概率会让某些消息路由到不同服务器。
|
||||
* 这个时候版本号就可以保住只有一台服务器可以对数据库做操作,不用担心多个服务器去操作数据。
|
||||
* 这个时候版本号就可以保证只有一台服务器可以对数据库做操作,不用担心多个服务器去操作数据。
|
||||
* 这是一个容错的操作,真实环境下很少发生。为了高性能必须要把服务器做成有状态的,这个容错操作就是最后一道保证数据一致的方案。
|
||||
* mongodb更新的时候是原子的,并发更新同一条数据只有一条数据会写入,第二条数据写入的时候版本号已经不一致了,所以老版本号的数据无法写入。
|
||||
* 写入的时候只要发现版本号不一致,就让缓存失效,重新读取数据库最新的数据。
|
||||
|
||||
@@ -15,6 +15,7 @@ package com.zfoo.storage.manager;
|
||||
|
||||
import com.zfoo.protocol.collection.CollectionUtils;
|
||||
import com.zfoo.protocol.exception.ExceptionUtils;
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
@@ -34,7 +35,6 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author jaysunxiao
|
||||
@@ -56,12 +56,12 @@ public class StorageManager implements IStorageManager {
|
||||
/**
|
||||
* 在当前项目被依赖注入,被使用的Storage
|
||||
*/
|
||||
private Map<Class<?>, Storage<?, ?>> storageMap = new HashMap<>();
|
||||
private final Map<Class<?>, Storage<?, ?>> storageMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 全部的Storage定义,key为对应的excel配置表,value为当前配置表是否在当前项目中使用
|
||||
*/
|
||||
private Map<Class<?>, Boolean> allStorageUsableMap = new HashMap<>();
|
||||
private final Map<Class<?>, Boolean> allStorageUsableMap = new HashMap<>();
|
||||
|
||||
public StorageConfig getStorageConfig() {
|
||||
return storageConfig;
|
||||
@@ -133,7 +133,7 @@ public class StorageManager implements IStorageManager {
|
||||
|
||||
Class<?> resourceClazz = (Class<?>) types[1];
|
||||
|
||||
Storage<?, ?> storage = StorageContext.getStorageManager().getStorage(resourceClazz);
|
||||
Storage<?, ?> storage = storageMap.get(resourceClazz);
|
||||
|
||||
if (storage == null) {
|
||||
throw new RuntimeException(StringUtils.format("静态类资源[resource:{}]不存在", resourceClazz.getSimpleName()));
|
||||
@@ -158,18 +158,21 @@ public class StorageManager implements IStorageManager {
|
||||
|
||||
@Override
|
||||
public void initAfter() {
|
||||
var unusableStorageClassList = allStorageUsableMap.entrySet().stream()
|
||||
allStorageUsableMap.entrySet().stream()
|
||||
.filter(it -> !it.getValue())
|
||||
.map(it -> it.getKey())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
unusableStorageClassList.forEach(it -> {
|
||||
storageMap.remove(it);
|
||||
});
|
||||
.forEach(it -> storageMap.remove(it));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Storage<?, ?> getStorage(Class<?> clazz) {
|
||||
var usable = allStorageUsableMap.get(clazz);
|
||||
if (usable == null) {
|
||||
throw new RunException("没有定义[{}]的Storage,无法获取", clazz.getCanonicalName());
|
||||
}
|
||||
if (!usable) {
|
||||
throw new RunException("Storage没有使用[{}],为了节省内存提前释放了它;只有使用ResInjection注解的Storage才能被动态获取", clazz.getCanonicalName());
|
||||
}
|
||||
return storageMap.get(clazz);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user