Cet article partagera avec vous 20 problématiques Redis que vous devez connaître et maîtriser. J'espère qu'il vous sera utile. Venez le récupérer !
Redis (Remote Dictionary Server
) est une base de données clé-valeur non relationnelle haute performance écrite en langage C. Contrairement aux bases de données traditionnelles, les données Redis sont stockées en mémoire, la vitesse de lecture et d'écriture est donc très rapide et elles sont largement utilisées dans la mise en cache. Redis peut écrire des données sur le disque, garantissant ainsi la sécurité des données et non leur perte, et les opérations Redis sont atomiques. [Recommandations associées : Tutoriel vidéo Redis]
Basé sur le fonctionnement de la mémoire, la vitesse de lecture et d'écriture de la mémoire est rapide.
Redis est mono-thread, ce qui évite les frais généraux de changement de thread et les problèmes de concurrence multi-thread. Un seul thread signifie que les requêtes réseau sont traitées par un seul thread, c'est-à-dire qu'un thread gère toutes les requêtes réseau lors de son exécution. Par exemple, le processus de persistance des données démarrera un autre thread.
Prend en charge plusieurs types de données, notamment String, Hash, List, Set, ZSet, etc.
Soutenir la persistance. Redis prend en charge deux mécanismes de persistance, RDB et AOF. La fonction de persistance peut efficacement éviter les problèmes de perte de données.
Affaires de soutien. Toutes les opérations de Redis sont atomiques et Redis prend également en charge l'exécution atomique après la fusion de plusieurs opérations.
Prend en charge la réplication maître-esclave. Le nœud maître synchronisera automatiquement les données avec le nœud esclave, permettant la séparation en lecture et en écriture.
Cache les données du hotspot pour soulager la pression sur la base de données.
En utilisant l'opération d'auto-incrémentation atomique de Redis, vous pouvez réaliser les fonctions de compteur, telles que compter le nombre de likes d'utilisateurs, de visites d'utilisateurs, etc.
File d'attente de messages simple Vous pouvez utiliser le propre mode de publication/abonnement de Redis ou List pour implémenter une file d'attente de messages simple et implémenter des opérations asynchrones.
Limiteur de vitesse peut être utilisé pour limiter la fréquence à laquelle un utilisateur accède à une certaine interface. Par exemple, le scénario de vente flash est utilisé pour empêcher les utilisateurs de subir une pression inutile causée par des clics rapides.
Relation amicale, utilisant certaines commandes de collection, telles que l'intersection, l'union, la différence, etc., pour réaliser des fonctions telles que des amis communs et des passe-temps communs.
Redis n'utilise que un seul cœur, tandis que Memcached peut utiliser plusieurs cœurs.
MemCached a une structure de données unique et n'est utilisé que pour mettre en cache les données, tandis que Redis prend en charge plusieurs types de données.
MemCached ne prend pas en charge la persistance des données et les données disparaîtront après le redémarrage. Redis prend en charge la persistance des données.
Redis fournit un mécanisme de synchronisation maître-esclave et des capacités de déploiement de cluster, qui peuvent fournir des services à haute disponibilité. Memcached ne fournit pas de mode cluster natif et doit s'appuyer sur le client pour écrire les données dans les fragments du cluster.
Redis est beaucoup plus rapide que Memcached.
Redis utilise un modèle de réutilisation des E/S multicanaux monothread, et Memcached utilise un modèle d'E/S multithread non bloquant.
Types de données de base :
1, String : le type de données le plus couramment utilisé. Les valeurs de type chaîne peuvent être des chaînes, des nombres ou des binaires, mais la valeur maximale ne peut pas dépasser 512 Mo.
2, Hash : Hash est une collection de paires clé-valeur.
3. Set : Un ensemble non ordonné et dédupliqué. Set fournit des méthodes telles que l'intersection et l'union, ce qui est particulièrement pratique pour réaliser des fonctions telles que les amis communs et l'attention commune.
4, List : Collection ordonnée et répétable, la couche inférieure est implémentée en s'appuyant sur une liste doublement chaînée.
5, SortedSet(ZSet) : Ensemble ordonné. Un paramètre score
est conservé en interne pour l'implémentation. Convient aux scénarios tels que les classements et les files d'attente de messages pondérées. score
的参数来实现。适用于排行榜和带权重的消息队列等场景。
特殊的数据类型:
1、Bitmap:位图,可以认为是一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在 Bitmap 中叫做偏移量。Bitmap的长度与集合中元素个数无关,而是与基数的上限有关。
2、Hyperloglog。HyperLogLog 是用来做基数统计的算法,其优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。典型的使用场景是统计独立访客。
3、Geospatial :主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如定位、附近的人等。
事务的原理是将一个事务范围内的若干命令发送给 Redis,然后再让 Redis 依次执行这些命令。
事务的生命周期:
使用MULTI
开启一个事务;
在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真正执行;
EXEC
命令进行提交事务。
一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性:
first:0>MULTI "OK" first:0>set a 1 "QUEUED" first:0>set b 2 3 4 "QUEUED" first:0>set c 6 "QUEUED" first:0>EXEC 1) "OK" 2) "OK" 3) "OK" 4) "ERR syntax error" 5) "OK" 6) "OK" 7) "OK"
WATCH命令
WATCH
命令可以监控一个或多个键,一旦其中有一个键被修改,之后的事务就不会执行(类似于乐观锁)。执行EXEC
命令之后,就会自动取消监控。
first:0>watch name "OK" first:0>set name 1 "OK" first:0>MULTI "OK" first:0>set name 2 "QUEUED" first:0>set gender 1 "QUEUED" first:0>EXEC (nil) first:0>get gender (nil)
比如上面的代码中:
watch name
开启了对name
这个key
的监控name
的值name
和gender
的值EXEC
命令进提交事务get gender
发现不存在,即事务a没有执行使用UNWATCH
可以取消WATCH
命令对key
的监控,所有监控锁将会被取消。
持久化就是把内存的数据写到磁盘中,防止服务宕机导致内存数据丢失。
Redis支持两种方式的持久化,一种是RDB
的方式,一种是AOF
的方式。前者会根据指定的规则定时将内存中的数据存储在硬盘上,而后者在每次执行完命令后将命令记录下来。一般将两者结合使用。
RDB
是 Redis 默认的持久化方案。RDB持久化时会将内存中的数据写入到磁盘中,在指定目录下生成一个dump.rdb
文件。Redis 重启会加载dump.rdb
文件恢复数据。
bgsave
是主流的触发 RDB 持久化的方式,执行过程如下:
BGSAVE
命令BGSAVE
命令直接返回。fork
操作创建子进程,fork操作过程中父进程会阻塞。fork
Types de données spéciaux : . HyperLogLog est un algorithme utilisé pour les statistiques de cardinalité. Son avantage est que lorsque le nombre ou le volume des éléments d'entrée est très grand, l'espace requis pour calculer la cardinalité est toujours fixe et très petit. Un scénario d'utilisation typique consiste à compter les visiteurs uniques.
3,
Géospatial🎜 : principalement utilisé pour stocker des informations de localisation géographique et exploiter les informations stockées dans des scénarios applicables tels que le positionnement, les personnes à proximité, etc. 🎜MULTI
pour ouvrir une transaction 🎜🎜🎜🎜Lors de l'ouverture d'une transaction, à chaque fois ; La commande d'opération sera insérée dans une file d'attente, et cette commande ne sera pas réellement exécutée ; la commande 🎜🎜🎜🎜EXEC
valide la transaction. 🎜🎜🎜🎜🎜🎜Une erreur dans une commande dans le cadre d'une transaction n'affectera pas l'exécution des autres commandes, et l'atomicité n'est pas garantie : 🎜appendfsync always //每次写入aof文件都会执行同步,最安全最慢,不建议配置 appendfsync everysec //既保证性能也保证安全,建议配置 appendfsync no //由操作系统决定何时进行同步操作
WATCH< La commande /code> peut surveiller une ou plusieurs clés. Une fois l'une des clés modifiée, les transactions suivantes ne seront pas exécutées (similaire au verrouillage optimiste). Après avoir exécuté la commande <code>EXEC
, la surveillance sera automatiquement annulée. 🎜//启动Redis实例作为主数据库 redis-server //启动另一个实例作为从数据库 redis-server --port 6380 --slaveof 127.0.0.1 6379 slaveof 127.0.0.1 6379 //停止接收其他数据库的同步并转化为主数据库 SLAVEOF NO ONE
watch name
active la surveillance de name
cette clé
🎜🎜Modifier La valeur du nom
🎜🎜Ouvrir la transaction a🎜🎜Les valeurs du nom
et du sexe
sont définies dans la transaction a🎜🎜Utiliser EXEC</code >Commande pour soumettre la transaction🎜🎜Utilisez la commande <code>get Gender
pour constater qu'elle n'existe pas, c'est-à-dire que la transaction a n'est pas exécutée🎜UNWATCH
pour annuler WATCH</ La commande code> surveille <code>key
et tous les verrous de surveillance seront annulés. 🎜RDB
et l'autre est la méthode AOF
. 🎜Le premier stockera régulièrement les données dans la mémoire du disque dur selon les règles spécifiées🎜, tandis que 🎜le second enregistrera la commande après l'exécution de chaque commande🎜. Généralement, une combinaison des deux est utilisée. 🎜RDB
est la solution de persistance par défaut de Redis. Lorsque RDB est persistant, les données dans la mémoire seront écrites sur le disque et un fichier dump.rdb
sera généré dans le répertoire spécifié. Le redémarrage de Redis chargera le fichier dump.rdb
pour restaurer les données. 🎜🎜bgsave
est le moyen courant de déclencher la persistance RDB. Le processus d'exécution est le suivant : 🎜🎜🎜BGSAVE
🎜🎜Le processus parent Redis détermine s'il existe actuellement en exécutant le processus enfants 🎜, s'il existe, la commande BGSAVE
revient directement. 🎜🎜Le processus parent effectue l'opération fork
🎜pour créer un processus enfant🎜 Le processus parent sera bloqué pendant l'opération fork. 🎜🎜Une fois le processus parent fork
terminé, 🎜le processus parent continue de recevoir et de traiter la demande du client🎜, et 🎜le processus enfant commence à écrire les données en mémoire dans le fichier temporaire sur le disque dur🎜 ; 🎜🎜Lors du processus enfant Une fois toutes les données écrites, l'ancien fichier RDB sera remplacé par ce fichier temporaire. 🎜🎜🎜Lorsque Redis démarre, il lira le fichier instantané RDB et chargera les données du disque dur dans la mémoire. Grâce à la persistance RDB, une fois que Redis se ferme anormalement, les données modifiées depuis la dernière persistance seront perdues. 🎜🎜Comment déclencher la persistance RDB :🎜手动触发:用户执行SAVE
或BGSAVE
命令。SAVE
命令执行快照的过程会阻塞所有客户端的请求,应避免在生产环境使用此命令。BGSAVE
命令可以在后台异步进行快照操作,快照的同时服务器还可以继续响应客户端的请求,因此需要手动执行快照时推荐使用BGSAVE
命令。
被动触发:
SAVE 100 10
,100秒内至少有10个键被修改则进行快照。BGSAVE
生成 RDB 文件并发送给从节点。shutdown
命令时,如果没有开启 AOF 持久化功能则自动执行·BGSAVE·。优点:
Redis 加载 RDB 恢复数据远远快于 AOF 的方式。
使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能。
缺点:
RDB方式数据无法做到实时持久化。因为BGSAVE
每次运行都要执行fork
操作创建子进程,属于重量级操作,频繁执行成本比较高。
RDB 文件使用特定二进制格式保存,Redis 版本升级过程中有多个格式的 RDB 版本,存在老版本 Redis 无法兼容新版 RDB 格式的问题。
AOF(append only file)持久化:以独立日志的方式记录每次写命令,Redis重启时会重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,AOF 是Redis持久化的主流方式。
默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly
参数启用:appendonly yes
。开启AOF方式持久化后每执行一条写命令,Redis就会将该命令写进aof_buf
缓冲区,AOF缓冲区根据对应的策略向硬盘做同步操作。
默认情况下系统每30秒会执行一次同步操作。为了防止缓冲区数据丢失,可以在Redis写入AOF文件后主动要求系统将缓冲区数据同步到硬盘上。可以通过appendfsync
参数设置同步的时机。
appendfsync always //每次写入aof文件都会执行同步,最安全最慢,不建议配置 appendfsync everysec //既保证性能也保证安全,建议配置 appendfsync no //由操作系统决定何时进行同步操作
接下来看一下 AOF 持久化执行流程:
所有的写入命令会追加到 AOP 缓冲区中。
AOF 缓冲区根据对应的策略向硬盘同步。
随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩文件体积的目的。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
当 Redis 服务器重启时,可以加载 AOF 文件进行数据恢复。
优点:
AOF可以更好的保护数据不丢失,可以配置 AOF 每秒执行一次fsync
操作,如果Redis进程挂掉,最多丢失1秒的数据。
AOF以append-only
的模式写入,所以没有磁盘寻址的开销,写入性能非常高。
缺点:
对于同一份文件AOF文件比RDB数据快照要大。
数据恢复比较慢。
Redis的复制功能是支持多个数据库之间的数据同步。主数据库可以进行读写操作,当主数据库的数据发生变化时会自动将数据同步到从数据库。从数据库一般是只读的,它会接收主数据库同步过来的数据。一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。
//启动Redis实例作为主数据库 redis-server //启动另一个实例作为从数据库 redis-server --port 6380 --slaveof 127.0.0.1 6379 slaveof 127.0.0.1 6379 //停止接收其他数据库的同步并转化为主数据库 SLAVEOF NO ONE
主从复制的原理?
当启动一个从节点时,它会发送一个 PSYNC
命令给主节点;
如果是从节点初次连接到主节点,那么会触发一次全量复制。此时主节点会启动一个后台线程,开始生成一份 RDB
快照文件;
同时还会将从客户端 client 新收到的所有写命令缓存在内存中。RDB
文件生成完毕后, 主节点会将RDB
文件发送给从节点,从节点会先将RDB
文件写入本地磁盘,然后再从本地磁盘加载到内存中;
Ensuite, le nœud maître enverra la commande d'écriture mise en cache dans la mémoire au nœud esclave, et le nœud esclave synchronisera les données
S'il y a une panne de réseau entre le nœud esclave et le nœud maître et le La connexion est déconnectée, elle se reconnectera automatiquement, après la connexion, le nœud maître ne synchronisera qu'une partie des données manquantes avec le nœud esclave.
Il existe un problème dans la réplication maître-esclave : elle ne peut pas basculer automatiquement et ne peut pas atteindre une haute disponibilité. Le mode Sentinelle résout ces problèmes. Le mécanisme sentinelle peut basculer automatiquement entre les nœuds maître et esclave.
Lorsque le client se connecte à Redis, il se connecte d'abord au Sentinel. Le Sentinel indiquera au client l'adresse du nœud maître Redis, puis le client se connectera à Redis et effectuera les opérations suivantes. Lorsque le nœud maître tombe en panne, Sentinel détecte que le nœud maître est en panne et réélira un nœud esclave performant pour devenir le nouveau nœud maître, puis informera les autres serveurs esclaves via le mode publication-abonnement pour les laisser changer. hôtes.
Comment ça marche
Sentinelle
envoie des messages au Maître
et à l'Esclave
qu'il connaît une fois par seconde > et les autres instances de Sentinel
envoient une commande PING
. Sentinel
以每秒钟一次的频率向它所知道的Master
,Slave
以及其他 Sentinel
实例发送一个 PING
命令。PING
命令的时间超过指定值, 则这个实例会被 Sentine
标记为主观下线。Master
被标记为主观下线,则正在监视这个Master
的所有 Sentinel
要以每秒一次的频率确认Master
是否真正进入主观下线状态。Sentinel
(大于等于配置文件指定值)在指定的时间范围内确认Master
的确进入了主观下线状态, 则Master
会被标记为客观下线 。若没有足够数量的 Sentinel
同意 Master
已经下线, Master
的客观下线状态就会被解除。若 Master
重新向 Sentinel
的 PING
命令返回有效回复, Master
的主观下线状态就会被移除。哨兵模式解决了主从复制不能自动故障转移、达不到高可用的问题,但还是存在主节点的写能力、容量受限于单机配置的问题。而cluster模式实现了Redis的分布式存储,每个节点存储不同的内容,解决主节点的写能力、容量受限于单机配置的问题。
Redis cluster集群节点最小配置6个节点以上(3主3从),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。
Redis cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。
哈希槽是如何映射到 Redis 实例上的?
对键值对的key
使用 crc16
算法计算一个结果
将结果对 16384 取余,得到的值表示 key
对应的哈希槽
根据该槽信息定位到对应的实例
优点:
slot
存储分布在多个节点,节点间数据共享,可动态调整数据分布;gossip
协议交换状态信息,用投票机制完成Slave
到Master
PING
pour une instance dépasse la valeur spécifiée, l'instance sera marquée comme subjectivement hors ligne par Sentine
. Si un Maître
est marqué comme subjectivement hors ligne, tous les Sentinel
qui surveillent ce Maître
doivent confirmer une fois par seconde< Que ce soit le code>Maître< /code> entre réellement dans l’état subjectif hors ligne. Lorsqu'un nombre suffisant de Sentinel
(supérieur ou égal à la valeur spécifiée dans le fichier de configuration) confirme que Maître
est bien entré dans l'état subjectif hors ligne dans le délai spécifié plage, alors Master
sera marqué comme objectivement hors ligne. S'il n'y a pas un nombre suffisant de Sentinel
pour accepter que Master
est hors ligne, le statut objectif hors ligne de Master
sera levé. Si Master
renvoie une réponse valide à la commande PING
de Sentinel
, le statut subjectif hors ligne de Master
sera déplacé. retirer.
crc16
pour la clé
de la paire clé-valeur pour calculer un résultat 🎜🎜🎜🎜 Le résultat est un module de 16384, et la valeur obtenue représente l'emplacement de hachage correspondant à la clé
🎜🎜🎜🎜L'instance correspondante est localisée en fonction des informations sur l'emplacement🎜🎜🎜🎜🎜Avantages : 🎜🎜🎜🎜Pas d'architecture centrale, 🎜Prend en charge l'expansion dynamique🎜 ; 🎜🎜Les données sont stockées et distribuées dans plusieurs nœuds selon le emplacement
, et les données sont partagées entre les nœuds 🎜La distribution des données peut être ajustée dynamiquement🎜. 🎜🎜🎜Haute disponibilité🎜. Le cluster est toujours disponible lorsque certains nœuds sont indisponibles. Le mode cluster peut réaliser un basculement automatique. Les nœuds échangent des informations d'état via le protocole gossip
et utilisent le mécanisme de vote pour terminer le transfert de Esclave
vers Maître
. code>. Inversion des rôles. 🎜🎜🎜🎜Inconvénients : 🎜🎜Les key
sur le même nœud. Lorsque plusieurs key
sont distribuées sur différents nœuds, la fonction de transaction ne peut pas être utilisée. utilisé. . key
在同一节点上的事务操作,当多个key
分布于不同的节点上时无法使用事务功能。key
作为数据分区的最小粒度,不能将一个很大的键值对象如hash
、list
等映射到不同的节点。1、被动删除(惰性)。在访问key时,如果发现key已经过期,那么会将key删除。
2、主动删除(定期)。定时清理key,每次清理会依次遍历所有DB,从db随机取出20个key,如果过期就删除,如果其中有5个key过期,那么就继续对这个db进行清理,否则开始清理下一个db。
3、内存不够时清理。Redis有最大内存的限制,通过maxmemory参数可以设置最大内存,当使用的内存超过了设置的最大内存,就要进行内存释放, 在进行内存释放的时候,会按照配置的淘汰策略清理内存。
当Redis的内存超过最大允许的内存之后,Redis 会触发内存淘汰策略,删除一些不常用的数据,以保证Redis服务器正常运行。
Redisv4.0前提供 6 种数据淘汰策略:
Least Recently Used
),最近使用。利用LRU算法移除设置了过期时间的keyRedisv4.0后增加以下两种:
内存淘汰策略可以通过配置文件来修改,相应的配置项是maxmemory-policy
,默认配置是noeviction
key
est la granularité minimale du partitionnement des données. Un objet clé-valeur volumineux tel que hash
, list
, etc. ne peut pas être mappé. différents nœuds. Ne prend pas en charge plusieurs espaces de base de données Redis en mode autonome peut prendre en charge jusqu'à 16 bases de données, et un seul espace de base de données peut être utilisé en mode cluster.
1.
Suppression passive (paresseuse). Lors de l'accès à la clé, s'il s'avère que la clé a expiré, la clé sera supprimée.
2. Supprimer activement (régulièrement). Nettoyez régulièrement les clés. Chaque nettoyage parcourra toutes les bases de données en séquence, supprimera au hasard 20 clés de la base de données et les supprimera si elles expirent. Si 5 clés expirent, continuez à nettoyer cette base de données, sinon commencez à nettoyer la base de données suivante.
3.
Nettoyer lorsque la mémoire est insuffisante. Redis a une limite de mémoire maximale. La mémoire maximale peut être définie via le paramètre maxmemory Lorsque la mémoire utilisée dépasse la mémoire maximale définie, la mémoire doit être libérée. Lorsque la mémoire est libérée, la mémoire sera nettoyée selon la stratégie d'élimination configurée.
Lorsque la mémoire de Redis dépasse la mémoire maximale autorisée, Redis déclenchera la stratégie d'élimination de la mémoire et supprimera certaines données rarement utilisées pour assurer le fonctionnement normal du serveur Redis.
Redisv4.0 propose 6 stratégies d'élimination des données
: : LRU (Least Récemment utilisé
), récemment utilisé. Utilisez l'algorithme LRU pour supprimer les clés avec un délai d'expiration défini
allkeys-lru: lorsque la mémoire est insuffisante pour accueillir les données nouvellement écrites, supprimez la clé la moins récemment utilisée de l'ensemble de données
volatile-ttlvolatile-random : Sélectionnez toutes les données de l'ensemble de données avec un délai d'expiration et éliminez-les
🎜🎜allkeys-random🎜 : Sélectionnez toutes les données de l'ensemble de données et l'éliminer 🎜🎜🎜 pas d'expulsion🎜 : Il est interdit de supprimer des données. Lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, la nouvelle opération d'écriture signalera une erreur🎜maxmemory-policy
, et la configuration par défaut est noeviction
. 🎜🎜Comment assurer la cohérence des données lors d'une double écriture entre cache et base de données ? 🎜🎜🎜1. Supprimez d'abord le cache, puis mettez à jour la base de données 🎜🎜🎜Lors d'une opération de mise à jour, supprimez d'abord le cache, puis mettez à jour la base de données. Lorsque les requêtes suivantes seront lues à nouveau, les nouvelles données seront lues à partir de la base de données et. puis mis à jour dans le cache. 🎜🎜Problèmes existants : après avoir supprimé les données mises en cache et avant de mettre à jour la base de données, s'il y a une nouvelle demande de lecture pendant cette période, les anciennes données seront lues de la base de données et réécrites dans le cache, provoquant à nouveau une incohérence, et les lectures ultérieures seront échouer. Ce sont toutes des données anciennes. 🎜🎜🎜2. Mettez d'abord à jour la base de données, puis supprimez le cache🎜🎜🎜Lorsque vous effectuez une opération de mise à jour, mettez d'abord à jour MySQL après succès, supprimez le cache, puis réécrivez les nouvelles données dans le cache lors des demandes de lecture suivantes. 🎜🎜Problème existant : pendant la période entre la mise à jour de MySQL et la suppression du cache, la demande de lecture concerne toujours les anciennes données mises en cache. Cependant, une fois la mise à jour de la base de données terminée, elle sera cohérente et l'impact sera relativement faible. 🎜🎜🎜3. Cache de mise à jour asynchrone🎜🎜🎜Une fois l'opération de mise à jour de la base de données terminée, le cache n'est pas directement exploité. Au lieu de cela, la commande d'opération est encapsulée dans un message et jetée dans la file d'attente des messages, puis Redis consomme lui-même la mise à jour. La file d'attente de messages peut garantir la cohérence de la séquence d'opérations de données et garantit que les données dans le système de cache sont normales. 🎜🎜🎜Pénétration du cache, avalanche de cache, panne de cache [Explication détaillée]🎜Pénétration du cache Redis, pénétration, concepts et solutions d'avalanche🎜🎜🎜🎜Pénétration du cache🎜🎜La pénétration du cache fait référence à l'interrogation d'une 🎜Données inexistantes 🎜, puisque le cache est écrit passivement en cas d'échec, si les données ne peuvent pas être trouvées dans la base de données, elles ne seront pas écrites dans le cache. Cela entraînera l'interrogation des données inexistantes dans la base de données à chaque fois qu'elles sont demandées, ce qui entraînera la perte. signification de la mise en cache. Lorsque le trafic est intense, la base de données peut se bloquer. 🎜🎜🎜🎜🎜Cache la valeur nulle🎜 et ne vérifiera pas la base de données. 🎜采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap
中,查询不存在的数据会被这个bitmap
拦截掉,从而避免了对DB
的查询压力。
布隆过滤器的原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,将元素通过散列函数映射之后会得到k个点,如果这些点有任何一个0,则被检元素一定不在,直接返回;如果都是1,则查询元素很可能存在,就会去查询Redis和数据库。
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重挂掉。
解决方法:在原有的失效时间基础上增加一个随机值,使得过期时间分散一些。
缓存击穿:大量的请求同时查询一个 key 时,此时这个 key 正好失效了,就会导致大量的请求都落到数据库。缓存击穿是查询缓存中失效的 key,而缓存穿透是查询不存在的 key。
解决方法:加分布式锁,第一个请求的线程可以拿到锁,拿到锁的线程查询到了数据之后设置缓存,其他的线程获取锁失败会等待50ms然后重新到缓存取数据,这样便可以避免大量的请求落到数据库。
public String get(String key) { String value = redis.get(key); if (value == null) { //缓存值过期 String unique_key = systemId + ":" + key; //设置30s的超时 if (redis.set(unique_key, 1, 'NX', 'PX', 30000) == 1) { //设置成功 value = db.get(key); redis.set(key, value, expire_secs); redis.del(unique_key); } else { //其他线程已经到数据库取值并回写到缓存了,可以重试获取缓存值 sleep(50); get(key); //重试 } } else { return value; } }
redis客户端执行一条命令分4个过程:发送命令、命令排队、命令执行、返回结果。使用pipeline
可以批量请求,批量返回结果,执行速度比逐条执行要快。
使用pipeline
组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline
命令完成。
原生批命令(mset和mget)与pipeline
对比:
原生批命令是原子性,pipeline
是非原子性。pipeline命令中途异常退出,之前执行成功的命令不会回滚。
原生批命令只有一个命令,但pipeline
支持多命令。
Redis 通过 LUA 脚本创建具有原子性的命令:当lua脚本命令正在运行的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。
在Redis中执行Lua脚本有两种方法:eval
和evalsha
。eval
命令使用内置的 Lua 解释器,对 Lua 脚本进行求值。
//第一个参数是lua脚本,第二个参数是键名参数个数,剩下的是键名参数和附加参数 > eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
lua脚本作用
1、Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令。
2、Lua脚本可以将多条命令一次性打包,有效地减少网络开销。
应用场景
举例:限制接口访问频率。
在Redis维护一个接口访问次数的键值对,key
是接口名称,value
是访问次数。每次访问接口时,会执行以下操作:
aop
拦截接口的请求,对接口请求进行计数,每次进来一个请求,相应的接口访问次数count
加1,存入redis。count=1
,并设置过期时间。因为这里set()
和expire()
组合操作不是原子操作,所以引入lua
脚本,实现原子操作,避免并发访问问题。private String buildLuaScript() { return "local c" + "\nc = redis.call('get',KEYS[1])" + "\nif c and tonumber(c) > tonumber(ARGV[1]) then" + "\nreturn c;" + "\nend" + "\nc = redis.call('incr',KEYS[1])" + "\nif tonumber(c) == 1 then" + "\nredis.call('expire',KEYS[1],ARGV[2])" + "\nend" + "\nreturn c;"; } String luaScript = buildLuaScript(); RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class); Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
PS:这种接口限流的实现方式比较简单,问题也比较多,一般不会使用,接口限流用的比较多的是令牌桶算法和漏桶算法。
更多编程相关知识,请访问:编程入门!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!