ã©ã®èšèªã§ãé«è² è·ã®ãããžã§ã¯ããéçºããã«ã¯ãç¹å¥ãªã¢ãããŒããšç¹å¥ãªããŒã«ã®äœ¿çšãå¿
èŠã§ãããPHP ã§ã®ã¢ããªã±ãŒã·ã§ã³ã«é¢ããŠã¯ãç¶æ³ãããã«æªåããŠãããšãã°æ¬¡ã®ãããªéçºãå¿
èŠã«ãªãããšããããŸãã
ä»åã®äž»åœ¹ã¯ symfony 2.3 ãã¬ãŒã ã¯ãŒã¯ãããŒã¹ã«ãã PHP ã¢ããªã±ãŒã·ã§ã³ã§ãããããã¯æŽæ°ããããžãã¹èšç»ã«ã¯ãŸã£ããå«ãŸããŠããŸããã ãã®ãããžã§ã¯ãã§ã¯ãéåžžã«æšæºçãªã»ãã·ã§ã³ ã¹ãã¬ãŒãžã«å ããŠã ããã¹ãŠããã£ãã·ã¥ãããããªã·ãŒ memcached: ããŒã¿ããŒã¹ããã³ API ãµãŒããŒãžã®ãªã¯ãšã¹ããžã®å¿çãããŸããŸãªãã©ã°ãã³ãŒãå®è¡ãåæããããã®ããã¯ãªã©ã ãã®ãããªç¶æ³ã§ã¯ãmemcached ã®æ éã¯ã¢ããªã±ãŒã·ã§ã³ã®åäœã«ãšã£ãŠèŽåœçã«ãªããŸãã ããã«ããã£ãã·ã¥ã®æ倱ã¯ãDBMS ãç¶ãç®ã§ããŒã¹ããå§ããããAPI ãµãŒãã¹ããªã¯ãšã¹ããçŠæ¢ãå§ããããããªã©ãæ·±å»ãªçµæããããããŸãã ç¶æ³ãå®å®ãããŸã§ã«æ°ååãããå Žåãããããã®éã¯ãµãŒãã¹ãéåžžã«é ããªãããå®å šã«å©çšã§ããªããªãå¯èœæ§ããããŸãã
æäŸããå¿ èŠããããŸãã ã»ãšãã©åŽåããããã«ã¢ããªã±ãŒã·ã§ã³ãæ°Žå¹³æ¹åã«ã¹ã±ãŒãªã³ã°ã§ããæ©èœãã€ãŸããœãŒã¹ã³ãŒããžã®å€æŽã¯æå°éã«æããããå®å šãªæ©èœãç¶æãããŸãã ãã£ãã·ã¥ãé害ã«èæ§ã®ãããã®ã«ããã ãã§ãªãããã£ãã·ã¥ã«ããããŒã¿æ倱ãæå°éã«æããããã«ããŠãã ããã
memcached èªäœã®äœãåé¡ãªã®ã§ãããã?
äžè¬ã«ãPHP ã® memcached æ¡åŒµæ©èœã¯ãããã«äœ¿ããåæ£ããŒã¿ãšã»ãã·ã§ã³ ã¹ãã¬ãŒãžããµããŒãããŸãã äžè²«ããã㌠ããã·ã¥ã®ã¡ã«ããºã ã«ãããå€ãã®ãµãŒããŒã«ããŒã¿ãåçã«é 眮ããã°ã«ãŒãå ã®ç¹å®ã®ãµãŒããŒã«åç¹å®ã®ããŒãäžæã«ã¢ãã¬ã¹æå®ã§ããŸãããŸããçµã¿èŸŒã¿ã®ãã§ã€ã«ãªãŒã㌠ããŒã«ã«ããããã£ãã·ã¥ ãµãŒãã¹ã®é«å¯çšæ§ã確ä¿ãããŸã (ãã ããæ®å¿µãªããã ããŒã¿ãªã).
ã»ãã·ã§ã³ ã¹ãã¬ãŒãžã䜿çšãããšç¶æ³ãå°ãè¯ããªããŸããæ§æã§ããããã«ãªããŸãã memcached.sess_number_of_replicas
ãã®çµæãããŒã¿ã¯è€æ°ã®ãµãŒããŒã«åæã«ä¿åãããXNUMX ã€ã® memcached ã€ã³ã¹ã¿ã³ã¹ã«é害ãçºçããå ŽåãããŒã¿ã¯ä»ã®ãµãŒããŒãã転éãããŸãã ãã ãããµãŒããŒãããŒã¿ãªãã§ãªã³ã©ã€ã³ã«æ»ã£ãå Žå (éåžžã¯åèµ·ååŸã«èµ·ãããŸã)ãäžéšã®ããŒã¯ãµãŒããŒã«æå©ã«åé
åžãããŸãã å®éãããã¯æ¬¡ã®ããšãæå³ããŸã ã»ãã·ã§ã³ããŒã¿ã®æ倱倱æããå Žåã«å¥ã®ã¬ããªã«ã«ã移åãããæ¹æ³ããªãããã§ãã
æšæºã©ã€ãã©ãªããŒã«ã¯äž»ã«ä»¥äžãç®çãšããŠããŸãã 暪å ã¹ã±ãŒãªã³ã°: ãã£ãã·ã¥ã巚倧ãªãµã€ãºã«å¢ãããå¥ã®ãµãŒããŒã§ãã¹ããããŠããã³ãŒããããã£ãã·ã¥ã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã ãã ããç§ãã¡ã®ç¶æ³ã§ã¯ãä¿åãããããŒã¿ã®éã¯æ°ã®ã¬ãã€ããè¶ ããããšã¯ãªããXNUMX ã€ãŸã㯠XNUMX ã€ã®ããŒãã®ããã©ãŒãã³ã¹ã§ååã§ãã ãããã£ãŠãæçšãªæšæºããŒã«ã¯ãå°ãªããšã XNUMX ã€ã®ãã£ãã·ã¥ ã€ã³ã¹ã¿ã³ã¹ãåäœç¶æ ã«ç¶æããªãããmemcached ã®å¯çšæ§ã確ä¿ããããšã ãã§ãã ãããããã®æ©äŒããã掻çšããããšã¯ã§ããŸããã§ãã... ããã§ããããžã§ã¯ãã§äœ¿çšããããã¬ãŒã ã¯ãŒã¯ã®å€ããæãåºããŠã¿ã䟡å€ããããŸãããã®ãããã¢ããªã±ãŒã·ã§ã³ããµãŒããŒã®ããŒã«ã§åäœãããããšãäžå¯èœã§ããã ã»ãã·ã§ã³ ããŒã¿ã®æ倱ãå¿ããŠã¯ãªããŸããããŠãŒã¶ãŒã®å€§éãã°ã¢ãŠãã«é¡§å®¢ã®ç®ãããããããã®ã§ãã
çæ³çã«ã¯ãããå¿
èŠã§ãã memcached å
ã®ã¬ã³ãŒãã®ã¬ããªã±ãŒã·ã§ã³ãšã¬ããªã«ã®ãã€ãã¹ ééããééãããã£ãå Žåã ãã®æŠç¥ã®å®æœã«ååããŠãããŸãã
ãã«ãŒã¿ãŒ
ããã¯ãFacebook ã®åé¡ã解決ããããã« Facebook ãéçºãã memcached ã«ãŒã¿ãŒã§ãã memcached ããã¹ã ãããã³ã«ããµããŒãããŠããŸãã memcached ã€ã³ã¹ããŒã«ãã¹ã±ãŒã«ãã éåžžèãªããããŒã·ã§ã³ã«ã mcrouter ã®è©³çŽ°ãªèª¬æã¯ã次ã®å Žæã«ãããŸãã
- ã¬ã³ãŒããè€è£œããã
- ãšã©ãŒãçºçããå Žåã¯ãã°ã«ãŒãå ã®ä»ã®ãµãŒããŒã«ãã©ãŒã«ããã¯ããŸãã
åå ã®ããã«ïŒ
ãã«ãŒã¿ãŒèšå®
ããã«èšå®ã«é²ã¿ãŸãã
{
"pools": {
"pool00": {
"servers": [
"mc-0.mc:11211",
"mc-1.mc:11211",
"mc-2.mc:11211"
},
"pool01": {
"servers": [
"mc-1.mc:11211",
"mc-2.mc:11211",
"mc-0.mc:11211"
},
"pool02": {
"servers": [
"mc-2.mc:11211",
"mc-0.mc:11211",
"mc-1.mc:11211"
},
"route": {
"type": "OperationSelectorRoute",
"default_policy": "AllMajorityRoute|Pool|pool00",
"operation_policies": {
"get": {
"type": "RandomRoute",
"children": [
"MissFailoverRoute|Pool|pool02",
"MissFailoverRoute|Pool|pool00",
"MissFailoverRoute|Pool|pool01"
]
}
}
}
}
ãªãããŒã«ã XNUMX ã€ããã®ã§ãããã? ãµãŒããŒãç¹°ãè¿ãããã®ã¯ãªãã§ãã? ãããã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã
- ãã®æ§æã§ã¯ãmcrouter 㯠request ã³ãã³ãã«åºã¥ããŠãªã¯ãšã¹ãã®éä¿¡å
ã®ãã¹ãéžæããŸãã ãã®ç·ã¯åœŒã«ããèšããŸã
OperationSelectorRoute
. - GET ãªã¯ãšã¹ãã¯ãã³ãã©ãŒã«éãããŸã
RandomRoute
é åãªããžã§ã¯ãéã§ããŒã«ãŸãã¯ã«ãŒããã©ã³ãã ã«éžæããŸãchildren
ã ãã®é åã®åèŠçŽ ã¯é çªã«ãã³ãã©ãŒã«ãªããŸããMissFailoverRoute
ããã¯ãããŒã¿ãå«ãå¿çãåä¿¡ãããŸã§ããŒã«å ã®åãµãŒããŒãééãããã®å¿çã¯ã¯ã©ã€ã¢ã³ãã«è¿ãããŸãã - ç¬å çã«äœ¿çšããå Žå
MissFailoverRoute
XNUMX ã€ã®ãµãŒããŒã®ããŒã«ãããå Žåããã¹ãŠã®ãªã¯ãšã¹ãã¯æåã«æåã® memcached ã€ã³ã¹ã¿ã³ã¹ã«éä¿¡ãããæ®ãã®ã€ã³ã¹ã¿ã³ã¹ã¯ããŒã¿ããªããšãã«æ®ãã®ãªã¯ãšã¹ããåä¿¡ããŸãã ãã®ãããªã¢ãããŒãã¯ã ãªã¹ãã®æåã®ãµãŒããŒã«éå°ãªè² è·ãããã£ãŠããŸã, ããã§ãç°ãªãé åºã®ã¢ãã¬ã¹ãæ〠XNUMX ã€ã®ããŒã«ãçæããããããã©ã³ãã ã«éžæããããšã«ããŸããã - ä»ã®ãã¹ãŠã®ãªã¯ãšã¹ã (ããã¯ã¬ã³ãŒã) ã¯æ¬¡ã䜿çšããŠåŠçãããŸãã
AllMajorityRoute
ã ãã®ãã³ãã©ãŒã¯ãããŒã«å ã®ãã¹ãŠã®ãµãŒããŒã«èŠæ±ãéä¿¡ããå°ãªããšã N/2 + 1 å°ã®ãµãŒããŒããã®å¿çãåŸ ã¡ãŸãã 䜿çšããAllSyncRoute
ãã®æ¹æ³ã§ã¯ãããã®è¯å®çãªå¿çãå¿ èŠã§ãããããæžã蟌ã¿æäœãäžæ¢ããå¿ èŠããããŸããã ãã¹ãŠ ã°ã«ãŒãå ã®ãµãŒã㌠- ãã以å€ã®å Žåã¯è¿ãããŸãSERVER_ERROR
ã mcrouter ã¯å©çšå¯èœãªãã£ãã·ã¥ã«ããŒã¿ãè¿œå ããŸãããåŒã³åºãã PHP é¢æ°ã¯ ãšã©ãŒãè¿ãããŸã ãããŠéç¥ãçæãããŸããAllMajorityRoute
ã¯ããã»ã©å³å¯ã§ã¯ãªãããŠãããã®ååãŸã§ã¯äžèšã®åé¡ãçºçããããšãªããµãŒãã¹ãåæ¢ããããšãã§ããŸãã
ã¡ã€ã³ãã€ãã¹ ãã®ã¹ããŒã ã¯ãå®éã«ãã£ãã·ã¥ã«ããŒã¿ããªãå Žåãã¯ã©ã€ã¢ã³ãããã®ãªã¯ãšã¹ãããšã« memcached ãžã® N åã®ãªã¯ãšã¹ããå®éã«å®è¡ããããšãããã®ã§ãã ãã¹ãŠ ããŒã«å ã®ãµãŒããŒã ããšãã°ãããŒã«å ã®ãµãŒããŒã®æ°ã XNUMX å°ã«æžããããšãã§ããŸããã¹ãã¬ãŒãžã®ä¿¡é Œæ§ãç ç²ã«ãªããŸããПãªã¯ãšã¹ãããããŒã®æ¬ èœãŸã§ã®åŠçé床ãåäžããè² è·ã軜æžãããŸãã
NB: mcrouter ã®åŠç¿ã«åœ¹ç«ã€ãªã³ã¯ãèŠã€ãããŸãã
ãã«ãŒã¿ãŒã®æ§ç¯ãšå®è¡
ç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ (ããã³ memcached èªäœ) 㯠Kubernetes ã§å®è¡ãããŸãããããã£ãŠãmcrouter ãããã«ãããŸãã ã®ããã« ã³ã³ããã®çµã¿ç«ãŠ ã䜿çšããŠãããŸã
NB: èšäºã«èšèŒãããŠãããªã¹ãã¯ãªããžããªã§å
¬éãããŠããŸã
configVersion: 1
project: mcrouter
deploy:
namespace: '[[ env ]]'
helmRelease: '[[ project ]]-[[ env ]]'
---
image: mcrouter
from: ubuntu:16.04
mount:
- from: tmp_dir
to: /var/lib/apt/lists
- from: build_dir
to: /var/cache/apt
ansible:
beforeInstall:
- name: Install prerequisites
apt:
name: [ 'apt-transport-https', 'tzdata', 'locales' ]
update_cache: yes
- name: Add mcrouter APT key
apt_key:
url: https://facebook.github.io/mcrouter/debrepo/xenial/PUBLIC.KEY
- name: Add mcrouter Repo
apt_repository:
repo: deb https://facebook.github.io/mcrouter/debrepo/xenial xenial contrib
filename: mcrouter
update_cache: yes
- name: Set timezone
timezone:
name: "Europe/Moscow"
- name: Ensure a locale exists
locale_gen:
name: en_US.UTF-8
state: present
install:
- name: Install mcrouter
apt:
name: [ 'mcrouter' ]
...ã¹ã±ããããŠã¿ãŸã ãã«ã ãã£ãŒãã èå³æ·±ãã®ã¯ãã¬ããªã«ã®æ°ã«åºã¥ããæ§æãžã§ãã¬ãŒã¿ãŒã®ã¿ãããããšã§ãã (誰ãããã£ãšç°¡æœã§ãšã¬ã¬ã³ããªãªãã·ã§ã³ãæã£ãŠããå Žåã¯ãã³ã¡ã³ãã§å ±æããŠãã ãã):
{{- $count := (pluck .Values.global.env .Values.memcached.replicas | first | default .Values.memcached.replicas._default | int) -}}
{{- $pools := dict -}}
{{- $servers := list -}}
{{- /* ÐапПлМÑеЌ ЌаÑÑОв ЎвÑÐŒÑ ÐºÐŸÐ¿ÐžÑЌО ÑеÑвеÑПв: "0 1 2 0 1 2" */ -}}
{{- range until 2 -}}
{{- range $i, $_ := until $count -}}
{{- $servers = append $servers (printf "mc-%d.mc:11211" $i) -}}
{{- end -}}
{{- end -}}
{{- /* СЌеÑаÑÑÑ Ð¿ÐŸ ЌаÑÑОвÑ, пПлÑÑаеЌ N ÑÑезПв: "[0 1 2] [1 2 0] [2 0 1]" */ -}}
{{- range $i, $_ := until $count -}}
{{- $pool := dict "servers" (slice $servers $i (add $i $count)) -}}
{{- $_ := set $pools (printf "MissFailoverRoute|Pool|pool%02d" $i) $pool -}}
{{- end -}}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mcrouter
data:
config.json: |
{
"pools": {{- $pools | toJson | replace "MissFailoverRoute|Pool|" "" -}},
"route": {
"type": "OperationSelectorRoute",
"default_policy": "AllMajorityRoute|Pool|pool00",
"operation_policies": {
"get": {
"type": "RandomRoute",
"children": {{- keys $pools | toJson }}
}
}
}
}
ããããã¹ãç°å¢ã«å±éãã以äžã確èªããŸãã
# php -a
Interactive mode enabled
php > # ÐÑПвеÑÑеЌ запОÑÑ Ðž ÑÑеМОе
php > $m = new Memcached();
php > $m->addServer('mcrouter', 11211);
php > var_dump($m->set('test', 'value'));
bool(true)
php > var_dump($m->get('test'));
string(5) "value"
php > # РабПÑаеÑ! ТеÑÑОÑÑеЌ ÑабПÑÑ ÑеÑÑОй:
php > ini_set('session.save_handler', 'memcached');
php > ini_set('session.save_path', 'mcrouter:11211');
php > var_dump(session_start());
PHP Warning: Uncaught Error: Failed to create session ID: memcached (path: mcrouter:11211) in php shell code:1
Stack trace:
#0 php shell code(1): session_start()
#1 {main}
thrown in php shell code on line 1
php > # Ðе завПЎОÑÑÑ⊠ÐПпÑПбÑеЌ заЎаÑÑ session_id:
php > session_id("zzz");
php > var_dump(session_start());
PHP Warning: session_start(): Cannot send session cookie - headers already sent by (output started at php shell code:1) in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Failed to write session lock: UNKNOWN READ FAILURE in php shell code on line 1
PHP Warning: session_start(): Unable to clear session lock record in php shell code on line 1
PHP Warning: session_start(): Failed to read session data: memcached (path: mcrouter:11211) in php shell code on line 1
bool(false)
php >
ãšã©ãŒã®ããã¹ããæ€çŽ¢ããŠãçµæã¯åŸãããŸããã§ããããã¯ãšãªã
NB: memcached ã® ASCII ãããã³ã«ã¯ãã€ã㪠ãããã³ã«ãããé ããäžè²«ããã㌠ããã·ã¥ã®æšæºæ段ã¯ãã€ã㪠ãããã³ã«ã§ã®ã¿æ©èœããŸãã ãã ããããã¯ç¹å®ã®ã±ãŒã¹ã§ã¯åé¡ãåŒãèµ·ãããŸããã
ã³ãã¯è¢ã®äžã«ãããŸããASCII ãããã³ã«ã«åãæ¿ããã ãã§ãã¹ãŠãæ©èœããŸãã ãã ãããã®å Žåãçããæ¢ãç¿æ
£ã¯ã
ã¯ããæ£ãããªãã·ã§ã³åã¯æ¬¡ã®ãšããã§ãã memcached.sess_binary_protocol
ã ãããç¡å¹ã«ããå¿
èŠããããŸããç¡å¹ã«ãããšãã»ãã·ã§ã³ãæ©èœãå§ããŸãã æ®ã£ãŠããã®ã¯ãmcrouter ãåããã³ã³ããã PHP ãåãããããã«é
眮ããããšã ãã§ãã
ãŸãšã
ãããã£ãŠãã€ã³ãã©ã¹ãã©ã¯ãã£ã®å€æŽã ãã§åé¡ã解決ã§ããŸãããmemcached ãã©ãŒã«ã ãã¬ã©ã³ã¹ã®åé¡ã解決ããããã£ãã·ã¥ ã¹ãã¬ãŒãžã®ä¿¡é Œæ§ãåäžããŸããã ã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠæãããªå©ç¹ã«å ããŠãããã«ãããã©ãããã©ãŒã äžã§äœæ¥ããéã«æäœã®äœå°ãçãŸããŸããããã¹ãŠã®ã³ã³ããŒãã³ãã«äºåããããšã管çè ã®äœæ¥ãå€§å¹ ã«ç°¡çŽ åãããŸãã ã¯ãããã®æ¹æ³ã«ã¯æ¬ ç¹ããããŸãããæŸèæãã®ããã«èŠãããããããŸãããããéãç¯çŽããåé¡ãåããæ°ããªåé¡ãåŒãèµ·ãããªãã®ã§ããã°ããªãããããªãã®ã§ããããïŒ
PS
ç§ãã¡ã®ããã°ããèªã¿ãã ãã:
- ãdappã§ç·Žç¿ã (äŸãšã㊠symfony-demo ã䜿çš):
ããŒã 1 (åçŽãªã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯) ОããŒã 2 (Helm ã䜿çšã㊠Docker ã€ã¡ãŒãžã Kubernetes ã«ãããã€ãã) ; - «
Kubernetes ãšã®ç掻ãã: HTTP ãµãŒããŒãã¹ãã€ã³äººã«æå©ã§ã¯ãªãã£ãçç± 'ã
åºæïŒ habr.com