Правильная настройка простого серверного кэша - PullRequest
1 голос
/ 24 августа 2010

Я пытаюсь настроить серверный кеш должным образом и ищу конструктивную критику в отношении настроек, которые у меня есть в настоящее время. Кеш загружается при запуске сервлета и больше никогда не изменяется, поэтому по сути это кеш только для чтения. Это очевидно должно остаться в памяти на всю жизнь сервлета. Вот как у меня это настроено

private static List<ProductData> _cache;
private static ProductManager productManager;

private ProductManager() {
    try {
        lookup();
    } catch (Exception ex) {
        _cache = null;
    }
}

public synchronized static ProductManager getInstance() {
    if (productManager== null) {
        productManager= new ProductManager();
    }
    return productManager;
}

Кеш настраивается сервлетом, как показано ниже:

private ProductManager productManager;

public void init(ServletConfig config) throws ServletException {
    productManager = ProductManager.getInstance();
}

И наконец, вот как я к нему обращаюсь:

public static ProductData lookup(long id) throws Exception {
    if (_cache != null) {
        for (int i = 0; i < _cache.size(); i++) {
            if (_cache.get(i).id == id) {
                return _cache.get(i);
            }
        }
    }

    // Look it up in the DB.
}

public static List<ProductData> lookup() throws Exception {
    if (_cache != null) {
        return _cache;
    }

    // Read it from the DB.

    _cache = list;
    return list;
}

Ответы [ 4 ]

1 голос
/ 24 августа 2010

Ты делаешь это нелегко.Шаблон со вкусом синглтона совершенно не нужен.Просто внедрите ServletContextListener, чтобы подключиться к запуску (и выключению) веб-приложения, чтобы можно было просто загрузить и сохранить данные в области приложения во время запуска веб-приложения.

public class Config implements ServletContextListener {

    private static final String ATTRIBUTE_NAME = "com.example.Config";
    private Map<Long, Product> products;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext context = event.getServletContext();
        context.setAttribute(ATTRIBUTE_NAME, this);
        String dbname = context.getInitParameter("dbname");
        products = Database.getInstance(dbname).getProductDAO().map();
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // NOOP.
    }

    public static Config getInstance(ServletContext context) {
        return (Config) context.getAttribute(ATTRIBUTE_NAME);
    }

    public Map<Long, Product> getProducts() {
        return products;
    }

}

который вы регистрируете в web.xml следующим образом:

<listener>
    <listener-class>com.example.Config</listener-class>
</listener>

Таким образом вы можете получить его в любом сервлете следующим образом:

Config config = Config.getInstance(getServletContext());
Map<Long, Product> products = config.getProducts();
// ...
1 голос
/ 24 августа 2010

Несколько вещей, которые приходят на ум:

  • Сохраните ваши кэшированные ProductData экземпляры на карте, чтобы вы могли искать кэшированный экземпляр в постоянное время, а не искать в списке.
  • Методы lookup не являются поточно-ориентированными.
  • Только lookup() будет фактически загружать значения из базы данных: вы не хотите, чтобы другой метод lookupтакже загрузить кэш (если он еще не загружен) для ускорения извлечения отдельных ProductData экземпляров?
0 голосов
/ 24 августа 2010

Пожалуйста, посмотрите на Suppliers.memoizeWithExpiration () Guava и MapMaker.Оба из них (в вашем случае, я думаю, MapMaker более актуален) позволят вам создать функцию кэширования за считанные минуты.

Избавьте себя от головной боли, используйте API:)

0 голосов
/ 24 августа 2010

Я бы порекомендовал вам сделать кеш как хэш-карту:

private static HashMap<Long,ProductData> _cache = new HashMap<Long,ProductData>();


// lookup by id becomes
return _cache.get(id);

// lookup of the complete collection of ProductData :
return _cache.values();

Вы можете сделать кеш статическим полем в классе ProductData, чтобы было меньше связующих и движущихся частей.

При использовании хеш-карты поиск по идентификатору будет по существу постоянным временем, тогда как поиск с помощью цикла for будет увеличиваться при увеличении числа ProductData со временем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...