memcache 란 무엇입니까?
Memcache 클러스터 환경의 캐시 솔루션
Memcache는 고성능 분산 메모리 객체 캐시 시스템입니다. 메모리에서 통합 및 거대한 해시 테이블을 유지하면 이미지, 비디오, 파일 및 데이터베이스 검색 결과를 포함한 다양한 형식으로 데이터를 저장하는 데 사용할 수 있습니다. 간단히 말해서, 데이터를 메모리로 호출 한 다음 메모리에서 읽어서 읽기 속도를 크게 향상시키는 것입니다.
Memcache는 Danga의 프로젝트입니다. 그것은 LiveJournal에 의해 처음 봉사되었습니다. 원래 LiveJournal의 액세스 속도를 높이기 위해 개발되었습니다. 나중에 많은 대형 웹 사이트에서 채택되었습니다.
MemCached는 데몬 모드에서 하나 이상의 서버에서 실행되며 언제든지 클라이언트 연결 및 작업을 수신합니다.
Memcache와 Memcached라는 두 가지 이름이있는 이유는 무엇입니까?
실제로 Memcache는이 프로젝트의 이름이며 Memcached는 서버 측의 주요 프로그램 파일 이름입니다. 당신은 내가 무슨 뜻인지 압니다. 하나는 프로젝트 이름이고 다른 하나는 기본 프로그램 파일 이름입니다. 온라인에서 많은 사람들이 이해하지 못하는 것을 보았으므로 혼합했습니다.
Memcached는 데이터베이스 부하를 줄이고 동적 애플리케이션의 액세스 속도를 향상시키는 데 사용되는 고성능 분산 메모리 객체 캐싱 시스템입니다. Memcached는 Danga Interactive가 LiveJournal.com에 대한 액세스를 개선하기 위해 개발했습니다. LJ는 초당 수천 개의 동적 페이지 방문을 보유하고 있으며 7 백만 명의 사용자가 있습니다. MemCached는 데이터베이스로드를 크게 줄이고 리소스를 더 잘 할당하며 액세스가 빠릅니다.
이 기사는 다음을 다룹니다.
memcache
Memcache는 Databasecalls, API Call 또는 Page Rendering의 결과에서 임의의 작은 데이터 (문자열, 객체)의 작은 덩어리에 대한 메모리 내 키 가치 저장소입니다.
즉, 키 값 쌍 데이터베이스 인 메모리 캐시 데이터베이스입니다. 데이터베이스는 다른 서비스에서 얻은 데이터를 메모리에 일시적으로 저장하기 위해 존재하며 반복 액세스 할 때 적중 캐시에서 직접 반환 할 수 있습니다. 이는 액세스 속도를 높이고 다른 서비스의 부하를 줄입니다. 여기서는 단일 서버 버전의 Memcache가 구현되며 여러 클라이언트 간의 동시 연결을 지원합니다.
클라이언트는 서버와 텔넷 연결을 설정 한 다음 Memcache 프로토콜에 따라 서버 캐시와 상호 작용합니다. 여기에 구현 된 지침은 Get, Set 및 Del입니다. 각 명령어의 형식을 살펴 보겠습니다.
세트
세트는 스토리지 명령입니다. 명령어의 특성을 저장할 때 기본 정보를 첫 번째 줄에 입력하고 두 번째 줄에 해당 값을 입력하십시오.
<key> <flags> <exptime> <bytes> [noreply]/r/n을 설정하십시오
<value>/r/n
스토리지가 성공하면 저장된 저장이 반환되며 지침에 Noreply 속성이 포함 된 경우 서버는 정보를 반환하지 않습니다.
이 지침의 각 도메인의 내용은 다음과 같습니다.
명령이 기준을 충족하지 않으면 서버는 오류를 반환합니다.
얻다
get는 get 명령 이며이 명령의 특성은 다음과 같습니다.
<key>*/r/n을 얻으십시오
여러 키의 전달 값을 지원합니다. 캐시가 하나 이상의 키를 누르면 해당 데이터가 반환되고 끝으로 끝납니다. 히트가 없으면 반환 된 메시지에는 키에 해당하는 값이 포함되어 있지 않습니다. 형식은 다음과 같습니다.
값 <키> <플래그> <바이트>/r/n <data block>/r/nvalue <key> <flags> <bytes>/r/n <data block>/r/nenddel
명령을 삭제하고 명령의 형식은 다음과 같습니다.
del <key> [noreply]/r/n
삭제가 성공하면 삭제 된/r/n을 반환합니다. 그렇지 않으면 _found가 반환됩니다. Noreply 매개 변수가 있으면 서버는 응답을 반환하지 않습니다.
자바 소켓
모든 Java 소켓은 TCP 프로토콜, 소켓 및 IO 스트림입니다. 나는 여기서 세부 사항으로 들어 가지 않을 것입니다. 내 일련의 기사를 참조 할 수 있습니다. Java Network 프로그래밍을 읽는 것이 좋습니다. 책.
코드 구현
여기에지도 함수에 문제가 있습니다. 기사 끝에서 내 프로젝트 주소로 이동하여 클래스 다이어그램을 볼 수 있습니다.
여기에서 명령 모드 및 공장 모드는 교육 생성 및 실행의 분리를 구현하는 데 사용됩니다. Command Factory는 CommandLine을 받고 명령 인스턴스를 반환합니다. 각 명령에는 고유 한 작업을 수행하는 실행 방법이 있습니다. DEL 명령의 특별 구현 만 여기에 게시됩니다.
/** * 다양한 지시문 * 현재 지원 GET, SET, DELETE * 및 CUSTOL * ERROR, END */PUBLIC Interface 명령 {/** * 실행 명령 * @Param Reader */void execute (Reader Reader, Writer Writer); / *** 명령 유형을 가져옵니다* @return*/ commandType getType ();} /*** 지침 공장의 단일 인스턴스*/public class commandFactory {private static commandFactory CommandFactory; 개인 정적 캐시 <item> memcache; private commandFactory () {} public static commandFactory getInstance (cache <item> cache) {if (commandFactory == null) {commandFactory = new CommandFactory (); memcache = 캐시; } return commandFactory; } / ** * 지시문 유형에 따라 명령을 얻습니다. } else if (commandline.matches ( "^get.*$")) {return new getCommand (Commandline, Memcache); } else if (commandline.matches ( "^del.*$")) {return new deleteCommand (commandline, memcache); } else if (commandline.matches ( "^end $")) {return new EndCommand (CommandLine); } else {return new ErrorCommand (CommandLine, ErrorCommand.erRortype.error); }}} /*** 캐시 지침 삭제*/public class deletecommand emplements 명령 {private final String 명령; 개인 최종 캐시 <item> 캐시; 개인 문자열 키; 사적인 부울 노초; public deletecommand (최종 문자열 명령, 최종 캐시 <item> 캐시) {this.command = 명령; this.cache = 캐시; initcommand (); } private void initcommand () {if (this.command.contains ( "noreply")) {noreply = true; } string [] info = command.split ( ""); key = info [1]; } @override public void execute (독자 독자, 작가 작가) {bufferedwriter bfw = (bufferedwriter) 작가; 항목 항목 = Cache.Delete (키); if (! noreply) {try {if (item == null) {bfw.write ( "not_found/r/n"); } else {bfw.write ( "deleted/r/n"); } bfw.flush (); } catch (ioexception e) {try {bfw.write ( "error/r/n"); bfw.flush (); } catch (ioexception e1) {e1.printstacktrace (); } e.printstacktrace (); }}} @override public CommandType getType () {return CommandType.search; }}그런 다음 메모리 서버를 구현하십시오. 첫 번째 최초의 기능을 지원하기 위해 LinkedTreeMap은 기본 구현으로 사용되며 가장 제거 된 방법이 다시 작성됩니다. 동시에 Cachemanager 배경 스레드는 만료 된 캐시 항목을 제 시간에 지우는 데 사용됩니다.
공개 클래스 memcache 구현 캐시 <item> {private logger = logger.getLogger (memcache.class.getName ()); // linkedhashmap을 사용하여 lru private static linkedhashmap <string, item> cache; 개인 최종 INT 최대 크기; // 부하 계수 개인 최종 플로트 DEFAULT_LOAD_FACTOR = 0.75F; public memcache (최종 int maxsize) {this.maxsize = maxsize; // maxsize에 도달 한 후 캐시가 자동으로 확장되지 않도록하십시오 int faruge = (int) math.ceil (maxsize /default_load_factor) + 1; this.cache = new LinkedHashMap <string, item> (용량, default_load_factor, true) {@override protected boolean removeeldestry (map.entry <string, item> eldest) {if (size ()> maxsize) {logger.info ( "캐시 번호는 최근에 사용 된 항목이 삭제 될 것입니다. } return size ()> maxsize; }}; // 동기화 된 액세스 수집을 구현합니다 .SynChronizedMap (캐시); } public synchronized boolean isfull () {return cache.size ()> = maxSize; } @override public item get (string key) {item item = cache.get (키); if (item == null) {logger.info ( "캐시의 키 :" + key + "존재하지 않는다"); 널 리턴; } else if (ited! = null && item.isexpired ()) {// 캐시가 만료되면 삭제 및 삭제 및 리턴 NULL LOGGER.INFO ( " + key +"value : " + item.getValue () +"만료 "); CACHE.REMOVE (키); 널 리턴; } logger.info ( "캐시에서 키 읽기 :" + key + "value :" + item.getValue () + "나머지 유효 시간" + item.remaintime ()); 반품 항목; } @override public void set (문자열 키, 항목 값) {logger.info ( "캐시에 대한 쓰기 키 :" + key + "value :" + value); cache.put (키, 값); } @override public item delete (string key) {logger.info ( "캐시에서 키 삭제 :" + 키); return cache.remove (키); } @override public int size () {return cache.size (); } @override public int capact () {return maxsize; } @override public iterator <map.entry <string, item >> iterator () {return cache.entryset (). iterator (); }} /*** 캐시 관리자* 배경 스레드* 캐시에서 만료 된 캐시 삭제*/public class cachemanager emplements runnable {private logger = logger.getLogger (cachemanager.class.getName ()); // 공용 캐시 캐시 <item> 캐시; public cachemanager (cache <item> cache) {this.cache = 캐시; } @override public void run () {while (true) {iterator <map.entry <string, item >> itemiterator = cache.iterator (); while (itemiterator.hasnext ()) {map.entry <string, item> entry = itemiterator.next (); 항목 item = entry.getValue (); if (item.isexpired ()) {logger.info ( "key :" + enther.getKey () + "value" + item.getValue () + "촉진, 데이터베이스에서 삭제"); Itemiterator.remove (); }} try {// 5 초마다 배경 프로그램을 실행합니다. TimeUnit.seconds.sleep (5); } catch (InterruptedException e) {e.printstacktrace (); }}}}마지막으로, 서버 소켓이 인터페이스에 바인딩되고 허용 된 소켓을 추가 스레드로 전달하는 다중 스레드 소켓 서버를 구현하십시오.
/*** 서버*/public class ioserver 구현 서버 {private boolean stop; // 포트 번호 개인 최종 int 포트; // 서버 스레드 개인 서버 소켓 서사 소켓; 개인 최종 로거 로거 = logger.getLogger (ioserver.class.getName ()); // 스레드 풀, 스레드 용량은 MaxConnection 개인 최종 ExecutorService ExecutorService입니다. 개인 최종 캐시 <item> 캐시; public ioserver (int port, int maxconnection, cache <item> cache) {if (maxConnection <= 0) 새로운 불법적 인 불법 행위 ( "지원되는 연결의 최대 수는 양의 정수"); this.port = 포트; ExecutorService = executors.newfixedthreadpool (maxconnection); this.cache = 캐시; } @override public void start () {try {serversocket = new serversocket (port); logger.info ( "서버는 포트"+포트+"에서 시작합니다. e.printstacktrace ()}}} {logger.log, "서버가 종료 될 예정입니다 ..."); ! /*** 각 클라이언트의 연결 처리* 최종 명령을 얻은 후 연결을 닫습니다. s*/public class sockethandler emplements runnable {private static logger = logger.getLogger (sockethandler.class.getName ()); 개인 최종 소켓 소켓; 개인 최종 캐시 <item> 캐시; 개인 부울 마감; public sockethandler (소켓 S, 캐시 <item> 캐시) {this.socket = s; this.cache = 캐시; } @override public void run () {try {// 소켓 입력 스트림 최종 버퍼드 리더 reader = new bufferedReader (new inputStreamReader (socket.getInputStream ()); // 소켓 출력 스트림 최종 버퍼링 라이터 Writer = New BufferedWriter (New OutputStreamWriter (socket.getOutputStream ()); CommandCordory CommandFactory = CommandFactory.getInstance (캐시); while (! finish) {Final String CommandLine = reader.Readline (); logger.info ( "ip :" + socket.getlocaladdress () + "지시 :" + commandline); if (commandline == null || commandline.trim (). isempty ()) {계속; } // 명령 팩토리를 사용하여 명령 인스턴스를 가져옵니다. 최종 명령 = CommandCommand (commandLine); command.execute (독자, 작가); if (command.getType () == commandType.end) {logger.info ( "연결을 닫으려는 요청"); 마무리 = true; }}} catch (ioexception e) {e.printstacktrace (); logger.info ( "" + socket.getLocalAddress () + ""에서 연결을 닫습니다. } 마침내 {try {if (socket! = null) {socket.close (); }} catch (ioexception e) {e.printstacktrace (); }}}}프로젝트 주소를 보려면 여기를 클릭하십시오. 당신이 그것이 꽤 좋다고 생각한다면, 나는 당신이 나에게 별을 줄 수 있기를 바랍니다.
참조
Memcached 공식 웹 사이트
Memcache 프로토콜
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.