为什么要使用Redis?
在游戏的跨服业务中:
- 如果需要多个服联动需要自定义多条跨服协议通讯(至少4条,跨服请求、返回,个人跨服请求返回),调试起来非常麻烦。
- 比较难保证每一个服的数据是同步的,经常发现某些服跟主服数据不一致的情况。
- 旧项目的跨服架构不支持玩家不在跨服发跨服个人请求,如果需要发生跨服请求,需要带大量的本服数据进行跨服请求。
是否能有一个应用在不消耗过多性能的情况独立在这些服外面的第三方应用做到统一调配几个服的数据,并且能屏蔽大多数跨服的细节专注本服的业务。所以我们使用了Redis。
先把结论放在前面:
- 在 Redisson 框架使用过程中,问题都是出现在自己的使用方法上而并非Redis上。
- Redis作为一个内存数据库还是很快。
1.在同一业务中,多次使用同步查询
错误发生的场景:
在同一业务中,误认为redis是内存数据库很快(事实上也是很快,但是会影响本机性能),不慎使用了多次请求。
1 | csharp复制代码/** |
1 | 复制代码结果:同一结果多次同步查询,消耗性能 |
2.在异步RFuture里面用同步方法,导致同时阻塞两个线程,最终导致所有线程阻塞
错误发生的场景:
同时查询多个参数的时候,需要起多个查询
如:同时需要A、B、C数据的时候,我们需要连续起查询
1 | arduino复制代码/** |
结果:
简单来说,就是netty线程都被阻塞了。Redisson希望你增加网络线程缓和一下并发
1 | vbscript复制代码new RedisTimeoutException("Command still hasn't been written into connection! Increase nettyThreads and/or retryInterval settings. Payload size in bytes: " + totalSize |
根据上面两个问题的解决方案:
总结来说就是要解决两件事:减少与redis服务端的通讯、到本地服务器尽量异步执行
基于查询的优化方案:
方案1:如果这个请求是用于了锁,那只需要查询一次,如果有修改最后在加回去
1 | ini复制代码/** |
方案2:如果改数据不是频繁修改,建议使用缓存(RLocalCachedMap)
1 | ini复制代码/** |
RLocalCachedMap 源码简析
- RLocalCachedMap 初始化的时候就会向redis服务器发送一个以自己命名的SUBSCRIBE 命令。
- RLocalCachedMap 在修改的时候,除了修改也会发一条以自己命名的PUBLISH 命令。接到这个命令的时候就会修改在本机的缓存 updateCache()。
RLocalCachedMap.init(初始化)
1 | ini复制代码private void init(String name, LocalCachedMapOptions<K, V> options, RedissonClient redisson, EvictionScheduler evictionScheduler) { |
==========================================================================================================================================================
基于修改的优化方案
以上说的就是 Redisson 查询上的优化,那添加(修改)。是不是也有优化的方案呢?
添加(修改)主要是从 减少与redis服务端的通讯 处理的。
方案1:使用Redis的管道
1 | ini复制代码这个比较简单,就是把几条命令合成一条命令发给redis服务端 |
方案2:使用Redis的脚本
首先说下RBatch的局限,如果我想在管道里面做运算的操作是不能做到的。
如: 卖商品,当库存到0的时候,就不需要再减了。不然就会变负数了。
上面这种场景RBatch是做不到的,这个时候就需要用到Redis的lua脚本了。
1 | swift复制代码/** |
本文转载自: 掘金