Scala和playframework在节点之间共享缓存

Scala和playframework在节点之间共享缓存,scala,playframework,Scala,Playframework,我有一个复杂的问题,我不知道哪一个是最好的解决办法 这是一个场景: 我在一个负载平衡器和一个数据库下有N台服务器 所有服务器都连接到数据库 所有服务器运行相同的应用程序 我想实现一个缓存,以减少响应时间并将HTTP调用服务器->数据库减少到最小 我实现了它,并且在一台服务器上工作得很好……但是我需要找到一种机制,当数据不再有效时,更新其他服务器中的所有其他缓存 例如: 我有服务器A和服务器B,它们都有自己的缓存。 例如,在来自外部的第一个请求获取用户信息时,服务器A会回复 他的缓存是空的,

我有一个复杂的问题,我不知道哪一个是最好的解决办法

这是一个场景:

  • 我在一个负载平衡器和一个数据库下有N台服务器

  • 所有服务器都连接到数据库

  • 所有服务器运行相同的应用程序

  • 我想实现一个缓存,以减少响应时间并将HTTP调用服务器->数据库减少到最小

    我实现了它,并且在一台服务器上工作得很好……但是我需要找到一种机制,当数据不再有效时,更新其他服务器中的所有其他缓存

    例如:

    我有服务器A和服务器B,它们都有自己的缓存。 例如,在来自外部的第一个请求获取用户信息时,服务器A会回复

    他的缓存是空的,所以他需要从数据库中获取信息

    第二个请求转到B,这里的服务器B缓存是空的,因此他需要从数据库中获取信息

    第三个请求也是在服务器A上,现在数据在缓存中,它会立即响应,而无需数据库请求

    服务器B上的第四个请求是写请求(例如更改用户名),服务器B可以对数据库进行更改并更新自己的缓存,从而使旧用户无效

    但是服务器A仍然有旧的无效用户

    因此,我需要一种服务器B与服务器a(或N台其他服务器)通信的机制,以使缓存中的数据无效/更新

    在scala play框架中,什么是最好的方法?

    此外,考虑到将来服务器可以是地理冗余,因此在不同的地理位置,在不同的网络中,由不同的ISP服务。

    当加载一个用户时(来自数据库的一个服务器请求更新所有服务器缓存),也可以更新所有其他缓存,这样所有服务器都可以为将来的请求做好准备

    希望我已经说清楚了


    谢谢

    这可能不是您想要自己构建的东西。但是有很多分布式缓存可以使用,比如Ehcache或InfiniSpan。我建议你研究一下这两种方法中的一种。

    这可能不是你想要自己构建的东西。但是有很多分布式缓存可以使用,比如Ehcache或InfiniSpan。我建议您研究一下这两种方法中的一种。

    因为您正在使用Play,它在引擎盖下已经使用了Akka,所以我建议使用Akka集群切分。这样,Play服务的实例将在启动时形成一个集群(包括故障检测等),并在它们之间组织哪个实例拥有特定用户的信息

    因此,继续处理您的请求时,对
    GET/userinfo/:uid
    的第一个请求将命中服务器A。请求处理程序对
    uid
    进行哈希处理(例如,使用3:一致的哈希处理很重要),并将其解析为碎片27。自从实例启动以来,这是我们第一次收到涉及shard 27中用户的请求,因此创建了shard 27,假设它归服务器a所有。我们向新的
    UserInfoActor
    发送一条消息(例如
    GetUserInfoFor(uid)
    ),该请求从数据库加载所需数据,将其存储在其状态,然后回复。Play API处理程序接收回复并生成对HTTP请求的响应

    对于第二个请求,它针对的是相同的
    uid
    ,但会命中服务器B。处理程序将其解析为shard 27,其集群分片知道A拥有该shard,因此它会向A上的
    UserInfoActor
    发送一条消息,表示该
    uid
    的数据在内存中。它使用信息进行回复,Play API处理程序根据回复生成对HTTP请求的响应

    这样,对于用户信息的所有后续请求(例如,第三个,相同的
    GET
    命中服务器A)都不会触及数据库,无论它们命中哪个服务器

    对于第四个请求,比如说是
    POST/userinfo/:uid
    ,并点击服务器B,请求处理程序再次将
    uid
    散列到shard 27,但这一次,我们向服务器A上的
    UserInfoActor
    发送
    updateUserInfo(uid,newInfo)
    消息。actor接收消息,更新数据库,更新内存中的用户信息并回复(可以是像
    Done
    这样的简单操作,也可以是新信息)。请求处理程序根据该回复生成响应

    这非常有效:我个人见过使用集群切分的系统在内存中保留TB,并以一致的一位数毫秒延迟运行,用于交互式查询的流分析。服务器崩溃,服务器上运行的参与者重新平衡到幸存的实例


    需要注意的是,任何与您的需求相匹配的东西都是分布式系统,您需要强大的一致性,也就是说,您要求它在网络分区下不可用(如果B无法向a传递更新,它别无选择,只能使请求失败)。一旦你开始谈论地理冗余和多个ISP,你就会经常看到分区。在网络分区下获得可用性的唯一方法是放松一致性需求,并接受有时
    get
    不会包含最新的
    PUT
    /
    POST
    /
    DELETE

    因为您使用的是Play,它在引擎盖下已经使用了Akka,我建议使用Akka集群切分。这样,Play服务的实例将在启动时形成一个集群(包括故障检测等),并在它们之间组织哪个实例拥有特定用户的信息

    因此,继续处理您的请求,对
    GET/userinfo/:uid
    的第一个请求将命中服务器A。请求处理程序