Organizations

  • 多重互相关联 这里实际上工作当中涉及到的数据库多重关联问题, 而且这是目前所有系统系统当中大概率会接触到的问题, 假设目前后台需要设计游戏邮件表处理游戏邮件发放, 这里初版表结构如下: CREATE TABLE `game_mail_list` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', `server_id` JSON NOT NULL COMMENT '发送的服务器id', `player_id` JSON NOT NULL COMMENT '发送的玩家id', `type` TINYINT(3) UNSIGNED NOT NULL COMMENT '邮件类型', `title` VARCHAR(255) NOT NULL COMMENT '邮件标题' COLLATE 'utf8mb4_unicode_ci', `content` LONGTEXT COMMENT '邮件内容' COLLATE 'utf8mb4_unicode_ci', `item` LONGTEXT COMMENT '附件内容', `create_time` INT(10) UNSIGNED NOT NULL COMMENT '创建时间', `push_time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '推送时间', `start_time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '展示开始时间', `end_time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '展示结束时间', `delete_time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '软删除时间', `update_uid` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '操作者', `check_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '审核状态: 0 代表等待审核, 1代表审核通过,2代表审核拒绝', `check_uid` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '审核处理人', `check_time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '审核时间', PRIMARY KEY (`id`) USING BTREE ) COMMENT ='玩家邮件列表' COLLATE = 'utf8mb4_unicode_ci' ENGINE = InnoDB ROW_FORMAT = DYNAMIC; 十分简单的表, 直接记录后台创建对应 服务器ID+玩家ID 即可, 基本上满足前期推送游戏邮件需求.
    架构 Created Thu, 09 Jan 2025 23:29:17 +0800
  • JPA-DataRedis多数据源切换 这里主要基于 SpringBoot 目前的 spring-boot-starter-data-redis Redis Repositories 依赖. 日常项目使用当中可能不止有单个 Redis, 有时候需要切换多个 Redis 方便读写数据, 这里目前网上数据比较少所以总结下. 首先就是引入目前组件依赖: <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 引入比较简单, 后续关键就是编写配置项, 这里就是相对比较复杂的阶段, 首先是定义 application.properties 内部配置: # ===================================== # Redis中心库 # ===================================== spring.data.redis.center.host=192.168.1.110 spring.data.redis.center.port=6379 spring.data.redis.center.password=redis2024 spring.data.redis.center.database=0 # ===================================== # Redis会话库 # ===================================== spring.data.redis.session.host=192.168.1.100 spring.data.redis.session.port=6379 spring.data.redis.session.password=redis2024 spring.data.redis.session.database=1 这两个就是不同库对象和连接, 之后就是加载具体配置备用: /** * 数据库多库配置, 这里编写集成数据库相关配置 */ @Configuration public class DataSourceConfig { /** * 注意: * 1.必须要利用 @Primary 指定默认数据库主库, 其他配置默认都为从库不需要配置该注解 * 2.@Bean最好手动声明指定全局配置数据源名称,也就是指定 name 配置 * 3.
    Java Created Sat, 28 Dec 2024 23:53:58 +0800
  • 全局动态数据 这里主要涉及到 SpringBoot 授权对话基于认证规范该怎么全局获取到玩家信息实体. 通用HTTP授权规范 一般授权完成授权之后会以 Header 形式追加以下格式结构: Authorization: <type> <credentials> type 字段包含有: Basic: 基本明文账号密码之后base64编码 Bearer: OAuth|JWT 授权机制, 目前最常见 ….., 其他可以自行了解 可以按照自身需求构建 JWT 或者直接采用唯一哈希对应放置在 Redis 关联即可, 用户重新登录会去 Redis 注销上一次的 token 映射. 言归正传就是当登录完全通过 HandlerInterceptor 检索出来 Token 在数据库|Redis查询到对应数据实体之后怎么让全局被访问. 网上很多说采用 ThreadLocal 直接线程本地变量保存, 这样其实最大问题是内部出现 Exception 会导致内存没办法回收, 最后到达一定量及就会出现大量内存泄露. 另外设置和释放都需要手动进行分配和注销, 比如在 HandlerInterceptor 当中: public class HandlerInterceptorConfigurer implements HandlerInterceptor { private static final ThreadLocal<UserModel> USER = new ThreadLocal<>(); /** * 请求拦截 */ @Override public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception { User.
    Java Created Sat, 28 Dec 2024 14:23:01 +0800
  • 数据中台 数据中台( Data Centered Platform ) 是现代化管理数据方案, 在常规后台和数据库之中追加层数据处理层; 也就是废除常规 Web <-> DB 架构演变成 Web <-> Center <-> DB 中间做数据清理. 这样相比常规架构有以下好处: 隔离子业务直接访问数据库, 保证数据安全性 统一数据获取入口, 打通业务平台直接让多套系统统一 避免重复的数据筛选工作, 直接请求通用中心获取数据 数据中间层方便数据高效筛选和获取 减少运维管理成本, 多套系统和数据库集中在单套分布式服务器 项目架构演变路程: 项目立项: 单套后台系统和单数据库提供服务, 没有太复杂的角色权限, 运维|运营 共用管理中心 项目发展: 数据量暴涨并且单库单表开始无法承载, 需要分库分表和后台执行常驻任务清洗数据 项目成熟: 角色细分, 运营|运维|渠道商|客服 等业务拆分出来做复杂权限操作和查询, 还需要大量数据筛选统计 这样构建的好处就是避免业务碎片化, 比如需要知道客服业务需要去登录 XXX客户中心, 需要渠道业务需要去登录 YYY渠道中心, 诸如此类多系统在新人理解业务时候带来思维凌乱的问题, 每个系统可能业务相同但是有好几份代码. 比如 A 中心本身代码有查询用户数据功能, B 中心也有类似业务但是实现的是另外代码业务, 后面扩展 C 中心也类似 当然也不是提倡什么业务一开始就直接采用这种复杂架构方式, 因为本身设计这种架构对于开发人员来说需要很深厚的技术功底, 同时也要对线上业务有比较深入接触才能知道对应架构痛点. 对于项目初期盲目采用数据中台架构会导致项目更加混乱, 项目初期数据量级本身没达到要这样处理的地步 项目迈入成熟阶段比较明显的特征就是获取效率越来越低下, 且业务开始有数据主体关联( 渠道 - 用户 开始建立强关联 ).
    架构 Created Tue, 24 Dec 2024 22:28:42 +0800
  • Neo4J部署 官网提供 搭建教程 涵盖了所有平台, 主要是硬件设备满足即可, 最低需要双核4G配置才能获取到较高效率. 这里采用系统 apt|yum 按照部署: # 注意目前官方对于Java版本有需求, 所以可能需要按照官方处理 # 配置官网源 wget -O - https://debian.neo4j.com/neotechnology.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/neotechnology.gpg echo 'deb [signed-by=/etc/apt/keyrings/neotechnology.gpg] https://debian.neo4j.com stable 5' | sudo tee -a /etc/apt/sources.list.d/neo4j.list sudo apt-get update # 查看安装版本 apt list -a neo4j # Ubuntu的话需要启用 universe 库, 否则可能安装失败 sudo add-apt-repository universe # 这里默认采用社区版, 付费版本需要另外配置 sudo apt-get install neo4j=1:5.26.0 // 社区版 # sudo apt-get install neo4j-enterprise=1:5.26.0 // 企业版 安装完成之后配置跟随启动和启动: # 启动之前最好重置下密码 sudo neo4j-admin dbms set-initial-password 密码 # 首次启动数据库前,建议使用 neo4j-admin 的 set-initial-password 命令定义本地用户 neo4j 的密码 sudo systemctl enable neo4j sudo systemctl start neo4j # 默认会启动WebGUI来提供测试: curl http://localhost:7474/ # 开发环境可以通过配置修改为全网访问, 正式环境别这样处理 # 修改全网访问: server.
    部署 Created Sat, 21 Dec 2024 20:43:18 +0800
  • 大数据处理 这里说明下当前的面临的环境困局: 单表可能超过2~3G/day, 主要玩家打点数据 多表需要关联查询, 内部带有强关联( A表依靠B|C表的数据 ) 数据要求长持久性, 数据需要运营存底且需要保持最少三个月处理 已经实行分库分表, 但还是没办法提高数据查询效率 在游戏当中会出现频繁记录打点信息, 用于追踪玩家操作从而还原出玩家具体的操作流程; 特别游戏准备开服时期更加需要玩家打点信息, 如果买量推广效果好的时候单日递增打点数据是十分庞大的. 同时按照运营需求的情况, 也许需要统计玩家对于游戏活动参与度, 方便运营和策划分析总结下次构建出活动. 游戏运营的数据库相比其他更加复杂( 当然比不过更加频繁的 实时IM 方面 ), 其中涉及到: 分服: 游戏服务交叉很复杂, 可能涉及到 单服务器分叉多个子服 情况 存盘: 游戏相关数据需要保持至少一年, 且数据量及其庞大 检索: 关联数据查询十分频繁, 统计日活跃|月活跃|季度活跃交叉查询特别频繁 如果没有概念, 那么以简单案例说明: # 运营需要做月度玩家盘点, 要求如下: # 1. 需要查询30天玩家留存, 支持以下维度查询 # 1.1 起始日期( start_time, end_time ) # 1.2 可以包含 全部| 充值玩家 |不充值玩家( is_recharge ) # 1.3 可以筛选指定充值金额区间的玩家统计 ( start_recharge, end_recharge ) # 1.4 支持对应服务器Id查询( server_id ) 以此说明表的大概格式如下:
    架构 Created Fri, 20 Dec 2024 23:04:23 +0800
  • 接口限流 如果从事过接口开发的时候发现过接口流量异常, 可能有针对接口进行 刷流量 的情况, 所以就需要对接口进行请求限流防止服务崩溃. 如果直接没有对接口进行限流任由网络刷接口会导致数据库|NoSQL服务直接崩溃, 比如数据库 oom kill 这里需要区分开发过程两种网络服务: 脚本语言: PHP等 编译语言: Java等 对于脚本类型的语言开发接口, 脚本服务并不是常驻内存服务就需要 Redis 做内存访问锁, 如下代码处理: $redis = new Redis(); // 假设获取到客户端IP $ip_address = "192.168.1.111"; // 直接判断 redis 之中Key是否存在 // 存在就是目前还在超时或者超时时间偏差值 $key = "timeout_{$ip_address}"; if($redis->exists($key)){ // 这里代表存在该Key需要判断是否超过指定时间 $value = $redis->get($key); // 计算Redis请求时间和当前时间的误差值 $now = time(); if(is_numeric($value) && (($now - $value) > 1) ){ exit("timeout"); // 防止请求过快直接拦截 } } // 写入接口请求的时间戳 $now = time(), $redis->set($key,$now); // 设置该请求时间 $redis->expire($key,1);// 设置1s之后超时销毁 上面是个简单的接口限流方式, 实际上还需要根据请求的路径 PATH_INFO 做限流让各自接口做不同限流方式.
    部署 Created Sun, 15 Dec 2024 22:25:04 +0800
  • 签到活动 常规来说手游内部的签到活动分为 7天签到(周签到) 和 30天签到(月签到) 的差异, 主要是增加玩家在线留存的手段. 这里采用 erlang 样例处理, 首先需要确定好结构: %%% @doc 7天签到记录(每周定时入库刷新), 保存进程内存 -record(sign_of_7, { ymd :: non_neg_integer(), % Ymd 格式的当天记录: 20241204 之类 state :: non_neg_integer() % 签到状态, 0 - 初始化| 1 - 可以签到 | 2 - 签到完成 }). %%% @doc 7天签到日志(签到完成保存), 保存数据库 -record(sign_of_7_log, { ymd :: non_neg_integer(), % 同上 item :: list() % 奖励 }). 这里就是设定 分钟级 别定时器确定上次签到更新时间, 比如 20241201 需要不断和当天 Ymd 做比较之后确认超过7天就刷新进度就行了. 同理30天签到也差不多是这种处理方式, 游戏内存只需要记录标识读取 Excel 道具发送给客户端消息即可, 日志库负责记录签到奖励数据入库.
    游戏架构 Created Wed, 04 Dec 2024 14:32:10 +0800
  • QFramework集成网络序打包 Unity 网络编程和其他网络服务端编程交互其实还有很大区别, 包含以下问题: 网络传输默认采用 字节序(小端序) 传输, 并不是服务端常用的 网络序(大端序) 默认字符串采用 Unicode 而非常规用的 UTF-8 字符串 对于网络序转化需要 bytes 反转下处理: // 依靠 Array.Reverse 讲字节序转网络序 Int32 value = 120; var buffer = BitConverter.GetBytes(value); Array.Reverse(buffer); // 翻转序列 对于字符串处理就需要编码处理下: // Unicode 转 UTF8 字节流 var value = "hello.world"; var buffer = Encoding.UTF8.GetBytes(value); var lengthBuffer = BitConverter.GetBytes(buffer.Length); Array.Reverse(lengthBuffer); // UTF8字节流 转 Unicode var buffer = new byte[length]; // 假设客户端返回二进制流 Encoding.UTF8.GetString(buffer, 0, length); // 转化 Unicode 这里主要用到 Encoding 和 BitConverter 方法来处理转化, 没什么需要说的.
    QFramework Created Sun, 17 Nov 2024 22:42:28 +0800
  • 资源下载 这里发掘到由 AI 批量生成的 Icon 模型, 在测试过几轮之后发现本身基于 CC BY 3.0 协议允许商用, 只需要在引用时署名作者来源即可. 在几轮测试之后发现这批 Icon 有极高的使用价值, 可以免去在商用开发初期时候浪费事件找对应 Icon 图标的问题, 可以有效加快游戏开发速度. 作者生成资源网站: game-icons 直接下载 transparent 资源包, 可以下载 black|white 两套资源作为切换反色处理的样式, 也可以直接下载 white 一套直接自己上色处理. 这里采用 Unity 作为游戏引擎处理来引入对应的资源 导入Unity 首先构建 Canvas 图层作为整体界面 UI: 最后就是构建出喜欢的 IconButton: 这就是直接利用 AI-Icon 导入的全过程.
    美术设计 Created Fri, 15 Nov 2024 12:40:08 +0800