Translate RU: cache, security

pull/502/head
voitau 2020-05-03 19:00:15 -07:00
parent d48069bd99
commit d4a15a48ba
1 changed files with 175 additions and 27 deletions

View File

@ -2522,7 +2522,15 @@ l10n:p -->
## Cache
TBD
<p align="center">
<img src="http://i.imgur.com/Q6z24La.png"/>
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Источник: Scalable system design patterns</a></i>
</p>
Кэширование улучшает время загрузки страницы и может уменьшить нагрузку на сервера и базы данных. При таком подходе, диспетчер сначали проверяет, делался ли запрос ране, чтобы найти ответ, который уже на него возвращался, сократив при этом время выполнения текущего запроса.
Базы данных работают оптимальным образом при равномерном распределении операций чтения и записи между их партициями (partitions). Популярные элементы могут нарушить равномерность распределения, создавая узкие места. Добавление системы кэширование перед базой данных может позволить сгладить неравномерность поступающего трафика.
<!-- l10n:p
### Client caching
@ -2532,7 +2540,7 @@ l10n:p -->
### Client caching
TBD
Системы кэширования могут находиться на клиентской стороне (ОС или браузер), [server side](#reverse-proxy-web-server), или в выделенном уровне для кэширования.
<!-- l10n:p
### CDN caching
@ -2542,7 +2550,7 @@ l10n:p -->
### CDN caching
TBD
[CDNs](#content-delivery-network) считаются одним из видов кэширования.
<!-- l10n:p
### Web server caching
@ -2552,7 +2560,7 @@ l10n:p -->
### Web server caching
TBD
[Reverse proxies](#reverse-proxy-web-server) и системы такие системы кэширование как [Varnish](https://www.varnish-cache.org/) могут выдавать как статический, так и динамический контент. Веб-сервера тоже могут кэшировать запросы, возвращая ответы не обращаюсь к серверам приложений.
<!-- l10n:p
### Database caching
@ -2562,7 +2570,7 @@ l10n:p -->
### Database caching
TBD
База данных обычно включает какое-то кэширование в конфигурации по умолчанию, которое оптимизировано для стандартных сценариев использования. Настройка этих параметров для конкретных шаблонов использования данных может еще больше увеличить её производительность.
<!-- l10n:p
### Application caching
@ -2586,7 +2594,21 @@ l10n:p -->
### Application caching
TBD
Системы кэширования в памяти (например, Memcached и Redis) являются хранилищами типа "ключ-значение", которые находятся между вашим приложением и хранилищем данных. Они обычно быстрее, так как данных хранятся в оперативной памяти, а не на жестком диске, как это обычно бывает в случае с базами данных. Количество оперативной памяти имеет больше ограничений, чем жесткий диск, поэтому [алоритмы очистки кэша](https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%BA%D1%8D%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F), как например [вытеснение давно неиспользуемых (Least recently used, LRU)](https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%BA%D1%8D%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F#Least_recently_used_(%D0%92%D1%8B%D1%82%D0%B5%D1%81%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B4%D0%B0%D0%B2%D0%BD%D0%BE_%D0%BD%D0%B5%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D1%83%D0%B5%D0%BC%D1%8B%D1%85)) помогают удалять из кэша "холодные" записи и оставлять в памяти "горячие".
Redis включает дополнительную функциональность:
* возможность сохранения данных (из памяти на диск)
* встроенные структуры данных, например сортированные множества или списки
Существует несколько уровней кэширования, которые можно обобщить в две категории: "запросы к БД" и "объекты":
* записи БД
* запросы
* сформированные сериализуемые объекты
* сформированный HTML
Как правило, стоит избегать кэширования файлов, так как такой подход усложняет клонирование и автоматическое масштабирование.
<!-- l10n:p
### Caching at the database query level
@ -2599,7 +2621,10 @@ l10n:p -->
### Caching at the database query level
TBD
При таком подходе результат сохраняется с ключом, которым является вычисленное хэш-значение для запросы в базу данных. Такой подход имеет ряд недостатков:
* Тяжело удалить закэшированный результат сложных запросов
* Если меняется значение одной ячейки данных, необходимо удалить все запросы, который могут содержать эти данные
<!-- l10n:p
### Caching at the object level
@ -2619,7 +2644,17 @@ l10n:p -->
### Caching at the object level
TBD
При таком подходе данные рассматриваются как объекты, аналогично объектам в коде приложения. Приложение собирает данные из базы в объект класса или структуру(ы) данных:
* Объект удаляется из кэша, если структура данных, которую он представляет, изменилась
* Возможна асинхронная обработка: новые объекты могуть собираться из текущий версий закэшированных объектов
Что можно кэшировать как объекты:
* Пользовательские сессии
* Полностью сформированные веб-страницы
* Потоки активности
* Графовые данные пользователя
<!-- l10n:p
### When to update the cache
@ -2629,7 +2664,7 @@ l10n:p -->
### When to update the cache
TBD
Для каждого сценария использования необходимо определять, какая стратегия очистки кэша подходит наилучшим образом, так как количество данных, которые можно хранить в системе кэширования, ограничено.
<!-- l10n:p
#### Cache-aside
@ -2665,7 +2700,33 @@ l10n:p -->
#### Cache-aside
TBD
<p align="center">
<img src="http://i.imgur.com/ONjORqk.png"/>
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Источник: From cache to in-memory data grid</a></i>
</p>
Приложение читает данных из хранилища и записывает в него. Система кэширования не взаимодействует с хранилищем. Приложение выполняет следующие действия:
* Ищет элемент в кэше, которой там ещё нет
* Загружает данные из БД
* Добавляет элемент в кэш
* Возвращает результат клиенту
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
Обычно так используется [Memcached](https://memcached.org/).
Последующие запросы на чтение данных, находящиейся в кэши, выполняются быстро. Также такой подход известен как ленивая загрузка. Только запрашиваемые данные попадают в систему кэширование, и не происходит его заполнения данными, которые не запрашиваются.
<!-- l10n:p
##### Disadvantage(s): cache-aside
@ -2677,7 +2738,9 @@ l10n:p -->
##### Disadvantage(s): cache-aside
TBD
* Если запришиваемые данные отсутствуют в кэше, выполняется три дополнительных действия, которые могут привести к заметной задержке
* Данные могут устареть, если они обновляются в БД. Для смягчение последствий этой проблемы используют время жизни (TTL), которое вызывает обновление элемента в кэше, либо делают сквозную запись
* Когда выходит из строя сервер кэширования, он заменяется новым сервером с пустым кэшем, что увеличивает задержку.
<!-- l10n:p
#### Write-through
@ -2713,7 +2776,33 @@ l10n:p -->
#### Write-through
TBD
<p align="center">
<img src="http://i.imgur.com/0vBc0hN.png"/>
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Источник: Scalability, availability, stability, patterns</a></i>
</p>
Приложение использует систему кэширования, как основной источник данных, считывая и записывая данные в него. Система кэширования в свою очередь записывает и считывает данных из БД:
* Приложение добавляет и обновляет элемент в системе кэширования
* Система кэширования синхронно записывает данные в БД
* Возвращается результат
Код приложения:
```python
set_user(12345, {"foo":"bar"})
```
Код системы кэширования:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
В целом, подход со сквозной записью является медленным из-за операции записи, но последующие операции чтения выполняются быстро. Пользователи предпочитают такие системы из-за допустимой задержки при обновлении данных, но не их чтении. Данные в системе кэширования не устаревают.
<!-- l10n:p
##### Disadvantage(s): write through
@ -2724,7 +2813,8 @@ l10n:p -->
##### Disadvantage(s): write through
TBD
* Когда добавляется новый сервер из-за отказа другого, либо масштабироавние, его кэш не содержит никаких элементов, пока данные не будут обновляеться в БД. Использование "отдельного" кэша может помочь смягчить последствия этой проблемы
* Большая часть записываемых данных может вообще не использоваться. Использование времени жизни данных (TTL) может смягчить последствия этой проблемы.
<!-- l10n:p
#### Write-behind (write-back)
@ -2743,7 +2833,16 @@ l10n:p -->
#### Write-behind (write-back)
TBD
<p align="center">
<img src="http://i.imgur.com/rgSrvjG.png"/>
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Источник: Scalability, availability, stability, patterns</a></i>
</p>
При таком подходе приложение делает следующее:
* Добавляет/обновляет элемент в системе кэширования
* Асинхронно делает запись в БД, улучшая скорость записи
<!-- l10n:p
##### Disadvantage(s): write-behind
@ -2754,7 +2853,8 @@ l10n:p -->
##### Disadvantage(s): write-behind
TBD
* Возможна потеря данных, если система кэширования выйдет из строя до сохранения данных в БД.
* Такую систему сложнее реализовать, чем "отдельный" или "сквозной" кэш.
<!-- l10n:p
#### Refresh-ahead
@ -2772,7 +2872,15 @@ l10n:p -->
#### Refresh-ahead
TBD
<p align="center">
<img src="http://i.imgur.com/kxtjqgE.png"/>
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Источник: From cache to in-memory data grid</a></i>
</p>
При таком подходе можно настроить автоматическое обновление закэшированных данных, к которым недавно обращались, не ожидая истечения их срока действия.
Кэширование методом "предварительного обновление" может уменьшить задержку, по сравнению с кэшем, который делает сквозное чтение, если можно точно определить, какие элементы могут быть запрошены в будущем.
<!-- l10n:p
##### Disadvantage(s): refresh-ahead
@ -2782,7 +2890,7 @@ l10n:p -->
##### Disadvantage(s): refresh-ahead
TBD
* Неточное определение элементов, которые могут понадобиться в будущем, может привести к ухудшению производительности.
<!-- l10n:p
### Disadvantage(s): cache
@ -2794,7 +2902,9 @@ l10n:p -->
### Disadvantage(s): cache
TBD
* Необходимость поддерживать согласованность данных в кэше и источнике данных, таком как БД, с помощью [инвалидации кэша](https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%BA%D1%8D%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F).
* Инвалидация кэша является сложной задачей, и включаещей дополнительную задаче по определению времени, когда кэш нужно обновлять.
* Необходимы изменения в приложении, например, добавление Redis или Memcached.
<!-- l10n:p
### Source(s) and further reading
@ -2810,7 +2920,13 @@ l10n:p -->
### Source(s) and further reading
TBD
* [From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [Scalable system design patterns](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [Introduction to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [Scalability](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
* [AWS ElastiCache strategies](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
* [Кэш - Wikipedia](https://ru.wikipedia.org/wiki/%D0%9A%D1%8D%D1%88)
<!-- l10n:p
## Asynchronism
@ -2826,7 +2942,13 @@ l10n:p -->
## Asynchronism
TBD
<p align="center">
<img src="http://i.imgur.com/54GYsSx.png"/>
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Источник: Intro to architecting systems for scale</a></i>
</p>
Асинхронные процессы позволяют сократить время запросов для трудоёмких операций по сравнению со случаями, когда эти операции выполняются синхронно. Они также могут помочь с выполением времязатратных операций, таких как периодическое агрегирование данных.
<!-- l10n:p
### Message queues
@ -2847,7 +2969,19 @@ l10n:p -->
### Message queues
TBD
Очереди сообщений позволяют принимать, хранить и доставлять сообщения. Если операция слишком медленная для синхронного выполнения, можно использовать очередь сообщений со следующим рабочим процессом:
* Приложение отправляет задачу в очередь, затем оповещает пользователя о состоянии задачи
* Рабочий процесс (воркер) берет задачу из очереди, выполняет её и посылает сообщение о том, что задача выполнена
При таком подходе пользователь не заблокирован и задача выполняется в фоне. В это время, клиентское приложение может частично обработать данные и сделать видимость выполнения. Например, сразу после публикации вашего сообщения в соц. сети, оно может появится в вашей ленте, но фактическая доставка этого сообщения фоловерам может занять некоторое время.
**[Redis](https://redis.io/)** - может использоваться как простой брокер сообщений (message broker), но сообщения могут быть утеряны.
**[RabbitMQ](https://www.rabbitmq.com/)** - широко распространен, но потребует адаптации к "AMQP" протоколу и поддержки серверов для его развертывания.
**[Amazon SQS](https://aws.amazon.com/sqs/)** - сервис, может иметь большую задержку и возможность доставки сообщений дважды.
<!-- l10n:p
### Task queues
@ -2859,7 +2993,9 @@ l10n:p -->
### Task queues
TBD
Очереди сообщений принимают задачи и связанные с ними данные, выполняют их, и затем доставляет их результаты. Они могут поддерживать планирование и использоваться для выполнения задач, которые требуют высоких вычислительных мощностей, в фоне.
Планирование есть в **Celery**, который в основном поддерживается на Python.
<!-- l10n:p
### Back pressure
@ -2869,7 +3005,7 @@ l10n:p -->
### Back pressure
TBD
Если очередь достигает больших размеров, ее размер может стать больше память, что приведет к запросам элементов, которых нет в кэши, увеличению количества операций чтения с жесткого диска и ухудшению производительности. [Обратное давление](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) может помочь, ограничивая размер очереди и поддерживая высокую пропускную способность и хорошее время отклика для задач, которые уже находятся в очереди. Как только очередь заполнится, клиентские приложения получают 503 код состояния HTTP ("Сервис недоступен"). Клиенты могут повторить запрос позже, в том числе и с [экспоненциальной выдержкой](https://ru.wikipedia.org/wiki/%D0%AD%D0%BA%D1%81%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B2%D1%8B%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0).
<!-- l10n:p
### Disadvantage(s): asynchronism
@ -2879,7 +3015,7 @@ l10n:p -->
### Disadvantage(s): asynchronism
TBD
* Для простых вычислений и процессов реального времени лучше подойдут синхронные операции, так как введение очередей добавит задержку и усложнят систему.
<!-- l10n:p
### Source(s) and further reading
@ -2892,7 +3028,10 @@ l10n:p -->
### Source(s) and further reading
TBD
* [It's all a numbers game](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [Applying back pressure when overloaded](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [Закон Литтла](https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BA%D0%BE%D0%BD_%D0%9B%D0%B8%D1%82%D1%82%D0%BB%D0%B0)
* [What is the difference between a message queue and a task queue?](https://www.quora.com/What-is-the-difference-between-a-message-queue-and-a-task-queue-Why-would-a-task-queue-require-a-message-broker-like-RabbitMQ-Redis-Celery-or-IronMQ-to-function)
<!-- l10n:p
## Communication
@ -3171,7 +3310,14 @@ l10n:p -->
## Security
TBD
Этот параграф было бы хорошо дополнить. [contributing](#contributing)!
Обеспечение безопасноcти - это обширная тема. Если у вас нет значительного опыта в безопасности, либо вы не подаётесь на вакансию, которая требует знаний по безопасности, возможно вам будет достаточно основ:
* Шифруйте данные во время передачи и при хранении
* Очищайте входные данные пользователи и любые параметры, которые доступны пользователю для избежания [межсайтового скриптинга](https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D1%8B%D0%B9_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B8%D0%BD%D0%B3) и [внедрения SQL-кода](https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_SQL-%D0%BA%D0%BE%D0%B4%D0%B0).
* Используйте параметризуемые запросы для предотвращения внедрения SQL-кода
* Используйте [принцип минимальных привилегий](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D0%BF%D1%80%D0%B8%D0%B2%D0%B8%D0%BB%D0%B5%D0%B3%D0%B8%D0%B9)
<!-- l10n:p
### Source(s) and further reading
@ -3183,7 +3329,9 @@ l10n:p -->
### Source(s) and further reading
TBD
* [API security checklist](https://github.com/shieldfy/API-Security-Checklist)
* [Security guide for developers](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
<!-- l10n:p
## Appendix