当前位置:网站首页>Pool de connexion redis personnalisé
Pool de connexion redis personnalisé
2022-07-02 09:20:00 【Niceyz】
Un entretien d'usine:Examiner la conception du service et certaines exigences en matière d'interface.
Interface 2 résoudre le problème,Exigence 1 Limitation du courant; Exigence II Interface idempotent;Exigence 3 Paramètres de temporisation de la programmation réseau;Exigence 4 Limitation du courant;
Exigence 5 RésolutionHttpClientProblèmes de sécurité des fils,Idées personnaliséesHttpClientPool de connexion.
Mauvaise écriture:Dans un scénario simultané,Allez, viens.1000Demandes secondaires,Établissement1000Connexions secondaires,Les frais généraux de connexion sont mortels.
Nous utilisonssocketDéfinir unhttpclient,Montre - moi.socketThread Unsafe Phenomenon:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* Description: SocketLe réseau est connecté àredis,À utiliserredisProtocole de connexion
* Author: yz
* Date: Created in 2021/1/6 11:14
*/
public class Connetion {
private String host;
private int post;
private Socket socket; // Thread Unsafe
private InputStream inputStream;
private OutputStream outputStream;
public Connetion(String host, int post) {
this.host = host;
this.post = post;
}
/**
* Déterminer si la connexion a été établie , Déterminer si la connexion est initialisée , Ou la connexion n'est pas déconnectée
*/
public boolean isConnection(){
if(socket !=null && inputStream !=null && socket.isClosed()){
return true;
}
try {
socket = new Socket(host,post);
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Envoyer une commande
*/
public String sendCommand(byte[] command){
if(isConnection()){
try {
// Le client écrit d'abord les données
outputStream.write(command);
// Lire la réponse du serveur
byte[] res = new byte[1024];
int length = 0;
while ((length=inputStream.read(res))>0){
return new String(res,0,length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
/**
* Description: redisClasse d'outils de protocole
* Author: yz
* Date: Created in 2021/1/6 11:41
*/
public class RedisProtocolUtils {
public static final String DOLIER = "$";
public static final String ALLERTSTIC = "*";
public static final String CRLE = "\r\n";
public static byte[] buildRespByte(Command command,byte[]... bytes){
StringBuilder sb = new StringBuilder();
sb.append(ALLERTSTIC).append(bytes.length+1).append(CRLE);
sb.append(DOLIER).append(command.name().length()).append(CRLE);
sb.append(command.name()).append(CRLE);
for (byte[] arg : bytes) {
sb.append(DOLIER).append(arg.length).append(CRLE);
sb.append(new String(arg)).append(CRLE);
}
return sb.toString().getBytes();
}
/**
* redis set,getLes ordres
*/
public enum Command{
SET,GET
}
}
/**
* Description:
* Author: yz
* Date: Created in 2021/1/6 15:01
*/
public class ClientRunalbe implements Runnable {
private BatRedisClient client;
private String value;
public ClientRunalbe(BatRedisClient client, String value) {
this.client = client;
this.value = value;
}
@Override
public void run() {
client.set("ant",value);
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Description: redis Le client de connexion contient redisAccord etsocket
* Author: yz
* Date: Created in 2021/1/6 11:53
*/
public class BatRedisClient {
private Connetion connetion;
public BatRedisClient(String host,int port){
connetion = new Connetion(host,port);
}
public String set(String key,String value){
String result = connetion.sendCommand(
RedisProtocolUtils.buildRespByte(RedisProtocolUtils.Command.SET,key.getBytes(),value.getBytes()));
System.out.println("Thread name:"+Thread.currentThread().getName()
+"[result]:"+result.replace("\r\n","")+"[value]:"+value);
return result;
}
public String get(String key){
String result = connetion.sendCommand(
RedisProtocolUtils.buildRespByte(RedisProtocolUtils.Command.GET,key.getBytes(),key.getBytes()));
return result;
}
public static void main(String[] args) {
BatRedisClient client = new BatRedisClient("localhost",6379);
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
// Il y a un phénomène : Le thread actuel lit à redis Données de réponse retournées à d'autres Threads
pool.execute(new ClientRunalbe(client,"123"+i));
}
}
}
Mise en œuvremianTest de méthode,20Exécution simultanée des threads,Les résultats sont les suivants::1,Non exécuté20Une fois,2,redis Les résultats retournés ont été collés ensemble , En fait, une demande obtient le résultat d'une autre demande
1,Non exécuté20Une fois: Plusieurs Threads partagent un socket, Quand un fil écrit à moitié ,cpu Il n'y avait plus de créneaux horaires au moment de l'expédition , Le deuxième thread obtient cupFilm temporel, Les données sont également écrites , Ces données qui n'ont pas été écrites seront également redisLire à, Mais ne peut pas être analysé ,redisImpossible de retourner la réponse, Thread read not responding ,EntréeioBlocage.
2,redis Les résultats retournés ont été collés ensemble : La quantité de données est faible au moment de l'envoi , Le paquet envoyé par le thread est complet ,Voilà.redis Après cela, il peut être résolu en deux requêtes , C'est aussi le retour normal des données ,Si le fil1ObtenircupDroit d'utilisation,InreadLors de la lecture des données, Peut lire toutes les données du tampon en même temps , Après analyse, on a trouvé que +OK+OKC'est la forme.
Résoudre avec un pool de Threads personnalisé socket Problème de sécurité multithreadé ,Prends ça.clientObjet placé surpoolDans la piscine
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque; // File d'attente bidirectionnelle
import java.util.concurrent.LinkedBlockingQueue; // File d'attente unidirectionnelle
/**
* Description: redisPool de connexion
* Author: yz
* Date: Created in 2021/1/6 15:19
*/
public class RedisClientPool {
private List<BatRedisClient> allObject;
private LinkedBlockingQueue<BatRedisClient> linkedBlockingQueue;
public RedisClientPool(String host,int port,int connectionCount){
allObject = new ArrayList<>();
this.linkedBlockingQueue = new LinkedBlockingQueue<>(10);
for (int i = 0; i < connectionCount; i++) {
BatRedisClient client = new BatRedisClient(host,port);
linkedBlockingQueue.add(client);
allObject.add(client);
}
}
/**
* AccèsclientConnexion
*/
public BatRedisClient getClient(){
try {
return linkedBlockingQueue.take(); // or poll
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
/**
* Oui.clientRetour au pool de connexion
*/
public void returnClient(BatRedisClient client){
if(client == null){
return;
}
if(!allObject.contains(client)){
throw new IllegalStateException(
"Returned object not currently part of this pool");
}
try {
linkedBlockingQueue.put(client);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Description: Utiliser la personnalisationredisPool de connexion
* Author: yz
* Date: Created in 2021/1/6 15:28
*/
public class ClientPoolRunable implements Runnable {
private RedisClientPool pool;
private String value;
public ClientPoolRunable(RedisClientPool pool, String value) {
this.pool = pool;
this.value = value;
}
@Override
public void run() {
BatRedisClient client = pool.getClient();
client.set("ant",value);
pool.returnClient(client);
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Description: TestsredisPool de connexion
* Author: yz
* Date: Created in 2021/1/6 15:30
*/
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
RedisClientPool redisClientPool = new RedisClientPool("localhost",6379,10);
for (int i = 0; i < 20; i++) {
pool.execute(new ClientPoolRunable(redisClientPool,"123"+i));
}
}
}
Mise en œuvremainTest de méthode,Les résultats sont les suivants:, Exactement. 20Une fois,Il n'est plus là.+OK+OKC'est un phénomène.
Élargir les connaissances:File d'attente
边栏推荐
猜你喜欢
DTM distributed transaction manager PHP collaboration client V0.1 beta release!!!
Dix ans d'expérience dans le développement de programmeurs vous disent quelles compétences de base vous manquez encore?
「Redis源码系列」关于源码阅读的学习与思考
洞见云原生|微服务及微服务架构浅析
企业级SaaS CRM实现
微服务实战|负载均衡组件及源码分析
【Go实战基础】gin 如何验证请求参数
Typeerror: X () got multiple values for argument 'y‘
Actual combat of microservices | discovery and invocation of original ecosystem implementation services
C4D quick start tutorial - Chamfer
随机推荐
[staff] time mark and note duration (staff time mark | full note rest | half note rest | quarter note rest | eighth note rest | sixteenth note rest | thirty second note rest)
Mirror protocol of synthetic asset track
In depth analysis of how the JVM executes Hello World
京东高级工程师开发十年,编写出:“亿级流量网站架构核心技术”
Redis installation and deployment (windows/linux)
西瓜书--第五章.神经网络
Cartoon rendering - average normal stroke
C4D quick start tutorial - Chamfer
Matplotlib swordsman line - layout guide and multi map implementation (Updated)
Double non undergraduate students enter the factory, while I am still quietly climbing trees at the bottom (Part 1)
Cloud computing in my eyes - PAAS (platform as a service)
Typeerror: X () got multiple values for argument 'y‘
「Redis源码系列」关于源码阅读的学习与思考
oracle删除表空间及用户
Microservice practice | fuse hytrix initial experience
西瓜书--第六章.支持向量机(SVM)
Microservice practice | teach you to develop load balancing components hand in hand
Knife4j 2.X版本文件上传无选择文件控件问题解决
Oracle modifies tablespace names and data files
双非本科生进大厂,而我还在底层默默地爬树(上)