Java 开发 2.0: 现实世界中的 Redis :Redis 如何在包含大量读取操作的应用程序中战胜 memcached

 我来答
shade0879
2013-10-18 · TA获得超过427个赞
知道答主
回答量:107
采纳率:100%
帮助的人:115万
展开全部
这里就不再逐个讨论了,我将会在一个实际应用程序开发场景中介绍其中的一些。使用Redis 作为一个缓存解决方案 我之前提到过,Redis 可轻易地用作一个缓存解决方案,碰巧我现在正好需要这样一个!在该应用程序示例中,我将 Redis 集成到我基于定位的移动 Web 服务中,称之为 Magnus。 如果您没有关注本系列,那么我会先使用 Play 框架实现 Magnus,从那时起我就已经在各种实现中开发和重构它了。Magnus 是一个简单服务,可以通过 HTTP PUT 请求使用 JSON 文档。这些文档描述了特定帐号的位置,表示持有移动设备的人。 现在,我想要将缓存集成到 Magnus,也就是说我想要通过将不常更改的数据存储在内存中以减少 I/O 流量。Magnus 缓存! 在清单 5 中的第一步中,可以通过 get 调用了解新引入的帐户名称(一个键)是否为 REdis 中的一个键。get 调用可以将帐户 ID 作为一个值返回,或者将返回 null。如果返回一个值,我将用其作为我的 acctId 变量。如果返回的是 null(表明该帐户名称不是 Redis 中一个键),那么我将在 MongoDB 查找该帐户值,并通过 set 命令将其添加到 Redis。 这里的优势是速度:接下来,被请求的帐户将提交一个位置,这样我就能够从 Redis 中获取其 ID(作为内存缓存),而不是转到 MongoDB 并带来额外读取 I/O 成本。清单5. 使用 Redis 作为内存缓存 "/location/:account" { put { def jacksonMapper = new ObjectMapper() def json = jacksonMapper.readValue(request.contentText, Map.class) def formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm") def dt = formatter.parse(json['timestamp']) def res = [:] try{ def jedis = pool.getResource() def acctId = jedis.get(request.parameters['account']) if(!acctId){ def acct = Account.findByName(request.parameters['account']) jedis.set(request.parameters['account'], acct.id.toString()) acctId = acct.id } pool.returnResource(jedis) new Location(acctId.toString(), dt, json['latitude'].doubleValue(), json['longitude'].doubleValue() ).save() res['status'] = 'success' }catch(exp){ res['status'] = "error ${exp.message}" } response.json = jacksonMapper.writeValueAsString(res) } } 注意,清单 5 中的 aMagnus 实现(使用 Groovy 编写)仍然使用一个 NoSQL 实现作为数据模型存储;它仅仅使用 Redis 作为一个缓存实现用于查询数据。因为我的主要帐户数据位于 MongoDB 中(事实上,它驻留在 MongoHQ.com 中),而我的 Redis 数据存储在本地运行。在随后查找帐户 ID 时,Magnus 速度将显著提升。 可是等等!我为什么同时需要 MongoDB 和 Redis?难道我就不能单独使用一个吗?ORM 的 Node.js 很多项目均提供 ORM 类映射用于 Redis,其中包括一个极富影响力的基于 Ruby 的备用方案,称为 Ohm。我检查了该项目基于 Java 的派生产品(称为 JOhm),但是最终决定使用一个为 Node 编写的派生产品。Ohm 及其派生项目的妙处在于他们允许您将一个对象模型映射到一个基于 Redis 的数据结构。因此,您的模型对象是持久性的,同时在大多数情况下其读取速度也非常之快。 有了Nohm,我便能够使用 JavaScript 快速重写我的 Magnus 应用程序并能立即持久化 Location 对象。在清单 6 中,我已定义了一个 Location 模型,该模型包括 3 个属性。(注意,我通过将 timestamp 设置为一个字符串而不是一个真实的时间戳,从而简化我的示例。)清单6. Node.js 中的 Redis ORM var Location = nohm.model('Location', { properties: { latitude: { type: 'float', unique: false, validations: [ ['notEmpty'] ] }, longitude: { type: 'float', unique: false, validations: [ ['notEmpty'] ] }, timestamp: { type: 'string', unique: false, validations: [ ['notEmpty'] ] } } }); Node 的 Express 框架使 Nohm Location 对象的使用变得十分简单。在我的应用程序 PUT 实现中,我可以捕获正在进入的 JSON 值,并通过 Nohm 的 p 调用将其导入到一个 Location 实例。然后我再检查该示例是否有效,如果有效,我会对其进行持久化。清单7. 在 Node 的 Express.js 中使用 Nohm app.put('/', function(req, res) { res.contentType('json'); var location = new Location; location.p("timestamp", req.body.timestamp); location.p("latitude", req.body.latitude); location.p("longitude", req.body.longitude); if(location.valid()){ location.save(function (err) { if (!err) { res.send(JSON.stringify({ status: "success" })); } else { res.send(JSON.stringify({ status: location.errors })); } }); }else{ res.send(JSON.stringify({ status: location.errors })); } }); 正如清单 7 所示,可以轻易地将 Redis 构建成一个极其快速的内存数据存储。在一些案例中,它甚至是一个比 memcached 更好的缓存!结束语 Redis 对于许多数据存储场景非常有用,因为它可以将数据持久化到磁盘(还因为它支持一个丰富的数据集),有时候,它是 memcached 的有力竞争对手。有些情况下,对于您的领域也是很有意义的,您可以使用 Redis 作为数据模型和队列的一个备份存储。Redis 客户端实现几乎可被移植到任何编程语言中。 Redis 不是 RDMBS 的完全替代品,也不是一个重量级存储,但是和 MongoDB 一样拥有丰富的功能。然而,在很多情况下,它可与这些技术共存。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式