当前位置:网站首页>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
边栏推荐
- 洞见云原生|微服务及微服务架构浅析
- Leetcode sword finger offer brush questions - day 22
- Oracle modify database character set
- 定时线程池实现请求合并
- Redis zadd导致的一次线上问题排查和处理
- [go practical basis] how to customize and use a middleware in gin
- Don't spend money, spend an hour to build your own blog website
- Cloudrev self built cloud disk practice, I said that no one can limit my capacity and speed
- Cartoon rendering - average normal stroke
- Win10 uses docker to pull the redis image and reports an error read only file system: unknown
猜你喜欢
概率还不会的快看过来《统计学习方法》——第四章、朴素贝叶斯法
西瓜书--第五章.神经网络
别找了,Chrome浏览器必装插件都在这了
Matplotlib swordsman - a stylist who can draw without tools and code
Matplotlib swordsman line - layout guide and multi map implementation (Updated)
Chrome用户脚本管理器-Tampermonkey 油猴
远程连接IBM MQ报错AMQ4036解决方法
Win10 uses docker to pull the redis image and reports an error read only file system: unknown
WSL installation, beautification, network agent and remote development
【Go实战基础】如何安装和使用 gin
随机推荐
Talk about the secret of high performance of message queue -- zero copy technology
[go practical basis] how to verify request parameters in gin
Matplotlib swordsman line - layout guide and multi map implementation (Updated)
【Go实战基础】gin 如何获取 GET 和 POST 的请求参数
hystrix 实现请求合并
Chrome浏览器标签管理插件–OneTab
远程连接IBM MQ报错AMQ4036解决方法
Redis sorted set data type API and application scenario analysis
[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)
ORA-12514问题解决方法
The channel cannot be viewed when the queue manager is running
JVM instruction mnemonic
Oracle修改表空间名称以及数据文件
聊聊消息队列高性能的秘密——零拷贝技术
Matplotlib剑客行——容纳百川的艺术家教程
Double non undergraduate students enter the factory, while I am still quietly climbing trees at the bottom (Part 1)
Don't look for it. All the necessary plug-ins for Chrome browser are here
企业级SaaS CRM实现
破茧|一文说透什么是真正的云原生
[go practical basis] how to bind and use URL parameters in gin