有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java是在HTTP servlet上缓存数据库数据的好方法吗?

我正在编写一个HTTP servlet(托管在Amazon Elastic Beanstalk上),作为我的Android应用程序的应用服务器。我的应用程序将从我的servlet请求数据,然后servlet将从数据库(SimpleDB)中提取数据

由于我的客户机请求可能很频繁,我想在servlet上实现一个缓存,它将缓存请求的数据,以减少数据库读取。目前,我只是将“ServerCache”对象初始化为servlet的成员变量。ServerCache包含缓存数据的列表,我会在运行时填充这些列表

看起来像这样

public class ServerCache {
/**
 * ServerCache is responsible for caching data on the server.
 * Create several data structures on the server to cache buy/sell listings as listing objects. 
 * For now, we will be able to cache the entirety of the database contents. 
 * -ES
 * 
 * Only one ServerCache should ever be made, at the init() of this server
 */

private List<BuyListing> listbl; //What is the danger of having this public vs. private
private List<SellListing> listsl;

public String BLlastError;
public String SLlastError;
public ServerCache()
{
    this.listbl = new ArrayList<BuyListing>();
    this.listsl = new ArrayList<SellListing>();

    this.BLlastError = "Initialized";
    this.SLlastError = "Initialized";
} //Setters and getters ommitted

它在这里初始化

public class HelloWorld extends HttpServlet {

private SimpleDBConnect SDB; // contains functions for accessing database
private ServerCache Cache;

//Various Constants
private static final String BUY_LISTINGS_DOMAIN = "BuyListings";
private static final String SELL_LISTINGS_DOMAIN = "SellListings";
private static final String USER_ID_DOMAIN = "UserIDs";
private static final String MESSAGES_DOMAIN = "Messages";



public HelloWorld() {
    super();
    SDB = new SimpleDBConnect();
    SDB.createConnection();
    Cache = new ServerCache();

    Cache.setListbl(SDB.getAllBL());
    Cache.setListsl(SDB.getAllSL());
    updateSDBStatus();
    updateServletStatus("Initialized");
    updateCacheStatus();

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
{
    response.getOutputStream().println("Servlet Works \n SimpleDB Status:" + SDB.dbConnectStatus + "\n \n SDB log:  " + this.SDBStatus + "\n \n Servlet log:    " + this.ServletStatus
            + "\n \n Buy Cache Status:  " + this.BLCacheStatus + "\n \n Sell Cache Status:  " + this.SLCacheStatus);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ... Some code ommitted, the following is a relevant part of how I handle request for data

         if (packet.getHeader() == Constants.BL_REQUEST || packet.getHeader() == Constants.SL_REQUEST)
            {               
                MsgStruct temp = new MsgStruct();   
                if (packet.getHeader() == Constants.BL_REQUEST){
                    temp.setHeader(Constants.BL_REQUEST);

                    Type listOfTestObject = new TypeToken<List<BuyListing>>(){}.getType();
                    String s = gson.toJson(Cache.getListbl(), listOfTestObject);

                    temp.setPayload(s);
                    receivedString = gson.toJson(temp);
                }

有没有理由认为在我的servlet上缓存一个版本的数据是个坏主意?这只是我在黑暗中摸索,因为从来没有人教过我在这种情况下该怎么做。我知道并发性是一个问题,但我认为在这种情况下它不重要吗

谢谢


共 (1) 个答案

  1. # 1 楼答案

    将缓存添加到程序中会使其变得复杂一点,特别是当您想要修改数据时。在这种情况下,数据库和缓存应该始终具有相同的数据,无论接收到哪些GETPOST请求可能写入数据库,也可能不写入数据库

    您可能遇到的一个问题是如何保持缓存与数据库同步。在写入数据库时,始终更新缓存是至关重要的,并确保在使用缓存完成请求时,返回的数据与数据库中包含的数据相同。您确实说过只缓存请求的数据,但如果数据被写回数据库,则必须检查缓存的数据是否也已更新

    您提到,您将只实例化该类的一个实例。遵循缓存的单例模式可能更有意义,有关更多信息,请参阅维基百科页面http://en.wikipedia.org/wiki/Singleton_pattern。基本上,这会导致缓存自身初始化,并确保没有其他代码可以生成另一个实例。构造函数将是私有的,您将编写一个getInstance()方法,让缓存返回实例化的ServerCache对象

    我选择这条路线的原因是,您总是有可能编写另一个需要访问数据库的servlet,并且在不将缓存设置为单实例的情况下,很难为其提供缓存访问(更不用说与多次读取相关的多线程问题)

    另一件需要记住的事情是,缓存将占用服务器上的RAM。缓存RAM使用量以换取访问时间,根据您的计划,您可能有很多空闲时间,也可能没有。还有一种可能性是,您可能只是在RAM中复制整个数据库,从而破坏了它的用途。你会花费大量的处理时间来确保你更新了数据库,但从来没有真正使用过它。同样,如果你看到反应能力有所改善,我认为这没有问题,只要你管理得当

    为了有效地使用缓存,你必须严格限制缓存对象的数量,去掉那些使用不多的对象,只保留那些被频繁访问的对象。我想说的最后一点是,我注意到你的缓存正在使用ArrayList。这些并不是搜索未排序数据的最有效的数据结构。数据库是用来存储数据的,所以数据库很可能有一个更高效的存储系统,在你的情况下,缓存只对非常少量的频繁访问但很少修改的数据有用