Lorsqu'un petit ensemble de clés concentre une part disproportionnée du trafic en lecture, le nœud principal devient un goulot d'étranglement. L'activation de la séparation lecture/écriture et l'ajout de nœuds en lecture seule permettent de répartir ces lectures sur l'ensemble des nœuds. Cette approche réduit la charge sur le nœud principal et augmente linéairement le débit de lecture à chaque ajout de nœud.
Cas d'utilisation
La séparation lecture/écriture convient aux charges de travail qui tolèrent des données légèrement obsolètes lors des pics d'écriture, car les nœuds en lecture seule se répliquent depuis le nœud principal de manière asynchrone, avec un décalage faible mais non nul. Voici quelques scénarios typiques :
Contenu de page mis en cache : caches HTML pour les pages d'accueil de sites web, actualisés rarement.
Classements de jeux : classements horaires où un léger délai de mise à jour n'a aucun impact significatif.
Données de prévisions météorologiques : données fréquemment interrogées et mises à jour selon un calendrier fixe.
Fonctionnement
Tous les nœuds en lecture seule répliquent les données depuis le nœud principal de manière asynchrone, offrant ainsi une cohérence à terme. Le nœud principal traite 100 % des requêtes d'écriture et 1/N des requêtes de lecture, où N représente le nombre total de nœuds (principal + lecture seule). Par exemple, avec un nœud principal et trois nœuds en lecture seule, N vaut 4 et les performances en lecture peuvent être multipliées par 4. Cela permet de réduire la pression sur le processeur, le trafic réseau et la surcharge des connexions sur le nœud principal.
Un composant Proxy intégré achemine automatiquement les requêtes : les requêtes d'écriture sont dirigées vers le nœud principal, tandis que les requêtes de lecture sont distribuées entre les nœuds en lecture seule. Aucune modification du code client n'est nécessaire pour les instances mono-zone.
La séparation lecture/écriture est prise en charge par les architectures standard (principal-réplica) et en cluster. Dans une architecture en cluster, chaque shard de données peut disposer de son propre nœud en lecture seule. Pour plus de détails sur l'architecture, consultez la rubrique Séparation lecture/écriture.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
Une instance déployée en mode cloud-native
Un type d'instance Redis Open-Source Edition, Tair (Enterprise Edition) optimisé pour la DRAM ou Tair (Enterprise Edition) optimisé pour la mémoire persistante
Une instance dotée d'au moins 1 Go de mémoire
Une instance haute disponibilité
Activer la séparation lecture/écriture
Sur la page des détails de l'instance, cliquez sur Node Management dans le volet de navigation de gauche, puis activez l'option Read/write Splitting. Pour des instructions détaillées, consultez la procédure d'activation de la séparation lecture/écriture.
Connecter votre client
Instances mono-zone
Les instances mono-zone exposent un seul endpoint. Le Proxy intégré achemine automatiquement les requêtes de lecture et d'écriture vers les nœuds appropriés. Connectez-vous en utilisant votre endpoint et votre mot de passe existants, sans modifier votre code.
Pour des exemples de connexion, consultez le tutoriel de connexion client.
Instances bi-zone
Les instances bi-zone exposent deux endpoints : l'un pour la zone principale (lecture et écriture) et l'autre pour la zone secondaire (lecture seule). Les clients situés dans la zone secondaire se connectent à l'endpoint de la zone secondaire pour les opérations de lecture, ce qui réduit la latence inter-zones. Les opérations d'écriture sont toujours dirigées vers l'endpoint de la zone principale.
Les exemples suivants utilisent la zone I de Hangzhou (zone principale) et la zone J de Hangzhou (zone secondaire).
Client de la zone principale — lecture et écriture
Un client situé dans la zone I de Hangzhou se connecte à l'endpoint de la zone principale pour effectuer à la fois des lectures et des écritures :
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class MasterReadWrite {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(200);
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
// Primary zone endpoint, port, and password
String host = "r-bp1vtq8tnrquy****pd.redis.rds.aliyuncs.com";
int port = 6379;
String password = "default:Passw***2";
JedisPool pool = new JedisPool(config, host, port, 3000, password);
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set("foo", "bar");
System.out.println(jedis.get("foo"));
}
catch (Exception e) {
// Handle timeouts or other exceptions.
e.printStackTrace();
}
finally {
if (jedis != null) {
jedis.close();
}
}
pool.destroy(); // On application exit, call this method to release connections and resources.
}
}
Client de la zone secondaire — lecture seule
Un client situé dans la zone J de Hangzhou se connecte à l'endpoint de la zone secondaire pour les lectures. L'endpoint de la zone secondaire est réservé aux opérations de lecture. Interceptez l'exception JedisDataException pour gérer correctement toute tentative d'écriture accidentelle :
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class ReplicaRead {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(200);
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
// Secondary zone endpoint, port, and password
String host = "r-bp1vtq8tnrquy****pd.redis.rds.aliyuncs.com";
int port = 6379;
String password = "default:Passw***2";
JedisPool pool = new JedisPool(config, host, port, 3000, password);
Jedis jedis = null;
try {
jedis = pool.getResource();
System.out.println(jedis.get("foo"));
}
catch (JedisDataException e) {
// The secondary zone endpoint is read-only. Catch this exception if a write command is sent by mistake.
e.getMessage();
}
catch (Exception e) {
// Handle timeouts or other exceptions.
e.printStackTrace();
}
finally {
if (jedis != null) {
jedis.close();
}
}
pool.destroy(); // On application exit, call this method to release connections and resources.
}
}