On Github Zhigalov / wsd-cache
Сделать мое приложение на порядок быстрее потратив на это пару часов.
Пережить нагрузку в «черную пятницу».
Статика (HTTP запросы)
Получение данных
Результаты вычислений
Шаблоны
var app = express();
app.get('/', (req, res) => {
fetch()
});
[ { name: 'Timor', region: 'Indonesia' }, { name: 'Mocha', region: 'Yemen' }, { name: 'Java', region: 'Indonesia' } ]
var app = express();
app.get('/', (req, res) => {
fetch()
.then(calculate)
});
[ { name: 'Timor', region: 'Indonesia' }, { name: 'Mocha', region: 'Yemen' }, { name: 'Java', region: 'Indonesia' } ]
{ Indonesia: [ 'Timor', 'Java' ], Mocha: [ 'Yemen' ] }
var app = express();
app.get('/', (req, res) => {
fetch()
.then(calculate)
.then(data => res.json(data));
});
app.listen(3000);
var cache;
app.get('/', (req, res) => {
if (cache) { return res.json(cache); }
fetch()
.then(calculate)
.then(data => cache = data)
.then(data => res.json(data));
});
Уменьшили время ответа
var cache;
app.get('/', (req, res) => {
cache = cache || fetch().then(calculate);
cache
.then(data => res.json(data))
.catch(() => cache = null);
});
Уменьшили время ответа
Уменьшили нагрузку
var LRU = require('lru-cache'); var cache = LRU({ maxAge: 3000 });
app.get('/', (req, res) => {
if (!cache.has('coffee')) {
var data = fetch().then(calculate);
cache.set('coffee', data);
}
cache.get('coffee')
.then(data => res.json(data))
.catch(() => cache.del('coffee'));
});
Уменьшили время ответа
Уменьшили нагрузку
Контролируем время жизни
var Redis = require('ioredis'); var cache = new Redis();
cache.get('coffee')
.then(data => {
if (data) { return data; }
return fetch().then(calculate)
.then(data => {
cache.set('coffee', data, 'EX', 3);
return data;
});
})
.then(data => res.json(data));
Уменьшили время ответа
Уменьшили нагрузку
Контролируем время жизни
Общий кэш для всех инстансов
1. Прочитать шаблон
2. Скомпилировать
3. Применить
var _ = require('lodash'); var str = '<%= date %>: "<%= error.message %>"'; module.exports = _.template(str);
var template = require('./template');
app.get('/', (req, res) => {
var myError = Error(':-(');
console.log(template({
date: new Date(),
error: myError
}));
});
// Wed May 29 2019 04:01:37 GMT+0200 (CEST): ":-("
{{# cache 'menu'}} <h1>Coffee</h1> <ul> {{#each items}} <li>{{name}}</li> {{/each}} </ul> {{/cache}}
Handlebars.registerHelper('cache', (key, options) => { if (!cache.has(key)) { cache.set(key, options.fn(options.data.root)); } return cache.get(key); });
HitRate = 'из кэша' / 'число запросов'
Кэшировать популярные данные
Не кэшировать песональные данные
Не кэшировать сложные комбинации
// ... app.listen(3000); var data = fetch().then(calculate); cache.set('coffee', data);
<script> var data = { '/coffee': { ... }, '/favorite': { ... }, '/userData': { ... } }; </script>
function request(url) {
return data[url]
? Promise.resolve(data[url])
: $.get(url);
}
function memoize(key, maxAge, fn) {
if (cache.has(key)) {
return Promise.resolve(cache.get(key));
}
return Promise.resolve()
.then(fn)
.then(results => {
cache.set(key, result, maxAge);
return result;
});
}
Легко менять реализацию кэша
Настрока кэширования моделей
cookie
sessionStorage
localStorage
function setItem(key, maxAge, value) { var data = JSON.stringify({ expire: Date.now() + maxAge, value: value }); localStorage.setItem(key, data); }
function getItem(key, maxAge, value) { var store = localStorage.getItem(key); var data = JSON.parse(store); if(data.expire > Date.now()) { return data.value; } }
cache.set('speaker', { name: 'Жигалов Сергей', twitter: '@sergey_zhigalov', email: 'zhigalov@yandex-team.ru' });
cache.set('assistant', { name: 'Мокеев Евгений' });