예를 들어 첫 번째 액세스 요청에서 json이 반환되었습니다. {"n": 1}
100번째 액세스 요청이 json을 반환합니다: {"n": 100}
데이터베이스에 쓴 다음 데이터베이스를 확인하여 결과를 반환하는 기존 방법은 동시성이 클 경우 어떻게 해야 합니까? 이것은 가장 간단한 질문이어야 합니다
예를 들어 첫 번째 액세스 요청에서 json이 반환되었습니다. {"n": 1}
100번째 액세스 요청이 json을 반환합니다: {"n": 100}
데이터베이스에 쓴 다음 데이터베이스를 확인하여 결과를 반환하는 기존 방법은 동시성이 클 경우 어떻게 해야 합니까? 이것은 가장 간단한 질문이어야 합니다
가장 간단한 방법은 자동 증가된 기본 키 id를 사용하여 mysql 테이블을 구축한 다음 각 요청에 대한 레코드를 삽입한 다음 해당 레코드를 읽는 것입니다. 읽기 ID는 원하는 값이 됩니다.
그러면 ID 값을 기준으로 높은 동시성 시나리오를 쉽게 처리할 수 있습니다. 예를 들어 [인스턴트 킬]은 ID가 300보다 작고 6으로 나누어지는 규칙을 사용하여 즉석 킬이 성공한 것으로 간주할 수 있습니다. ID가 300보다 작고 6으로 나누어지는 규칙을 사용하여 즉석 킬이 성공했다고 간주할 수 있습니다. [복권]은 ID가 100(1%)으로 나누어지는 규칙을 당첨으로 사용할 수 있습니다.
직접 구현한다면 소켓 요청을 처리하고 전역 변수를 유지하는 단일 스레드 무한 루프에 지나지 않습니다. 이미 만들어진 mysql을 사용하는 것만큼 편리하고 안정적이지는 않습니다.
java
인 경우 전역 AtomicLong
이 요구 사항을 충족할 수 있습니다. getAndIncrement
원자 연산과 volatile
수정이 추가되고 다른 언어인 경우에도 유사합니다
redis에서 setnx(id)를 사용하면 단일 스레드가 매번 1씩 증가를 보장하고, 메모리 내 데이터베이스이기도 하므로 매우 빠릅니다.
읽기 작업: 캐시 사용
쓰기 작업: 대기열을 사용한 비동기 쓰기
순수 Java에서는 카운터 개체를 싱글톤으로 만들고 filter
을 통해 계산기를 1씩 늘리려는 모든 요청을 차단할 수 있습니다(동기화 필요). {n : 100}
, n
가 데이터베이스에서 가져온다는 것이 무슨 뜻인지 모르겠습니다.
실제로 원하는 것은 요청에 따라 대기열에 추가되고 처리되는 영구 메모리 대기열입니다.
단일 머신에서는 Linux의 /dev/shm에서 SQLite를 읽고 쓸 수 있습니다. 메모리 파일 시스템(tmpfs).
파일을 읽을 때 네트워크를 통과할 필요가 없으며 메모리 상주, 잠금, 자동 증가 및 고유 제약 조건을 구현할 필요가 없습니다.
<code><?php header('Content-Type: text/plain; charset=utf-8'); // sudo mkdir -m 777 /dev/shm/app $file = '/dev/shm/app/data.db3'; $ddl = " BEGIN; CREATE TABLE IF NOT EXISTS queue ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER ); CREATE UNIQUE INDEX IF NOT EXISTS queue_user_id_idx ON queue(user_id); COMMIT; "; if(!file_exists($file)) { //多核下多进程并发时可能都会进入到这个判断分支,所以DDL中要用IF NOT EXISTS $db = new PDO('sqlite:'.$file); $db->exec($ddl); // pdo_sqlite 的 query 和 prepare 不支持一次执行多条SQL语句 } else { $db = new PDO('sqlite:'.$file); } $stmt = $db->prepare('INSERT INTO queue(user_id) VALUES(?)'); $stmt->execute(array(time())); //time()换成你的用户ID echo $stmt->rowCount()."\n"; //查询中受影响(改动)的行数,插入失败时为0 echo $db->lastInsertId(); //插入的自增ID,插入失败时为0 // php -S 127.0.0.1:8080 -t /home/eechen/www >/dev/null 2>&1 & // ab -c100 -n1000 http://127.0.0.1:8080/</code>
가장 간단한 방법은 자동 증가를 위해 redis의 zset을 사용하는 것인데, 이는 효율적이고 간단합니다. 단일 머신을 사용하는 경우에는omiclong 사용을 고려할 수도 있습니다(종료하고 다시 시작하면 무효화됩니다)