Por que o Redis é rápido?
Redis será usado no projeto, porque redis pode ser usado como um cache e pode processar 10w de dados por segundo simultaneamente. Mas você sabe por que o acesso do redis é tão rápido? Você poderia dizer que o redis é baseado na memória, com base no armazenamento KV, single threaded .... Espere, por que o single-threaded é mais rápido?
Na verdade, o Redis é um modelo de multiplexação baseado em NIO. No ambiente Windows, é a multiplexação do select, e no ambiente Linux é a multiplexação do epoll. Algumas pessoas podem perguntar, o que é multiplexação.
Multiplexing
Simplificando, o Redis passa a leitura de dados para o kernel para fazer
Multiplexing
O Redis colocará n conexões de cliente em uma coleção (aqui está um processo) e, em seguida, chamará epoll (essa função não existe no Windows) ou selecionará a função para colocar a coleção no kernel do sistema operacional para processamento, orientado por eventos, O kernel obterá a conexão com os dados e os lerá ciclicamente.A complexidade de tempo é O (1).
Se você perguntar o que é NIO? Você precisa de conhecimento adicional de NIO.
Estrutura de valor Redis
5 estruturas comuns
estrutura de valor
cenas a serem usadas
Corda
Por exemplo, a conta oficial do WeChat pode usar o valor de String para contar o número de leituras
|
|
Pode ser o número de série global do sistema distribuído
|
|
dicas: você pode usar o comando setnx + timeout para fazer bloqueios distribuídos. Há um projeto sobre meu bloqueio distribuído redis no github: dislock
Além do redis poder ser usado como um bloqueio distribuído, o zookeeper também pode ser usado como um bloqueio distribuído (com base no nome do nó exclusivo e no mecanismo do observador). Comparado com o redis, o zookeeper é mais forte do que o redis na consistência final, mas seu desempenho será mais fraco do que o redis. projeto de bloqueio distribuído github: distributelock
Bitmap
Ele pode contar quantas vezes o usuário se conectou em qualquer janela de tempo
Bitmap é uma matriz binária com comprimento ilimitado (quando o comprimento é 2 bilhões, ele ocupa mais de 200 MB de memória). O valor na matriz é 0 ou 1. Conforme mostrado na figura acima, se o usuário sean efetuar login no 4º dia, é
|
|
Faça login no dia 9 como
|
|
E assim por diante. A última linha conta o número de vezes que o valor é 1 entre o primeiro índice e o último índice.
Também podemos usar bitmap para contar o número de usuários ativos
|
|
dicas: O famoso filtro Bloom pode ser implementado com bitmap
Cerquilha
hash pode armazenar informações relacionadas ao carrinho de compras
Conforme mostrado acima: a identificação do usuário é a chave, a identificação do produto é arquivada e a quantidade do produto é armazenada como valor. Pode exibir informações do carrinho de compras.
|
|
A estrutura hash tem as seguintes vantagens e desvantagens:
vantagem
1) Armazenamento consolidado de dados semelhantes, conveniente para gerenciamento de dados
2) Comparado com a operação de string, consome menos memória e cpu
3) Em comparação com o armazenamento de string, economiza mais espaço
Desvantagem
1) A função de expiração não pode ser usada no campo, mas apenas na chave
2) A arquitetura do cluster Redis não é adequada para uso em larga escala
Em geral, o hash pode ser usado para armazenar agregação de página de detalhes e os dados vêm da agregação de diferentes bibliotecas.
Lista
A lista pode ser usada como uma estrutura de dados, como filas, pilhas, etc.
Cenários de mensagens do Weibo e mensagens da conta oficial
|
|
Listar operações comuns
|
|
Conjunto
conjunto pode ser usado como um miniprograma de loteria WeChat
|
|
Também pode ser usado para WeChat e curtidas do Weibo
|
|
O modelo de atenção Weibo e WeChat pode ser realizado por meio de operações coletivas
|
|
definir operações comuns
|
|
Em geral, o conjunto pode ser usado para desduplicação, loteria e outras operações
Zset
zset é um conjunto ordenado de desduplicação, que pode ser usado para implementar classificações
Resumo: zset pode ser usado em cenários como placares e virada de página. zset pode ser usado como uma fila de atraso, a pontuação é o ponto de atraso no tempo, o valor da porta é obtido sequencialmente na obtenção e pode ser retirado se o carimbo de data / hora atual for igual à pontuação.
A estrutura de dados subjacente do zset é uma tabela de salto, uma lista especial vinculada, que é excelente para pesquisar, adicionar e excluir. Para conhecimentos específicos, consulte o artigo:
GEO
redis também pode suportar consulta de localização geográfica, adequado para desenvolvimento LBS
Comandos comuns
Corrente
A nova estrutura "Stream" começou no Stream 5.0. Cenário de uso: cenário produtor consumidor (semelhante ao MQ)
Comandos comuns
Exemplo
|
|
Agora, o redis é comumente usado no 3.x, e as listas também podem ser usadas para filas de mensagens. Poucas pessoas usam o stream.
Cluster Redis
Para construção de cluster, consulte: construção de cluster Redis3.0
Preocupações com o cluster
1、增加了slot槽的计算,是不是比单机性能差?
共16384个槽,slots槽计算方式公开的,HASH_SLOT=CRC16(key)mod16384。
为了避免每次都需要服务器计算重定向,优秀的java客户端都实现了本地计算,并且缓存服务器slots分配,有变动时再更新本地内容,从而避免了多次重定向带来的性能损耗。
2、redis集群大小,到底可以装多少数据?
理论是可以做到16384个槽,每个槽对应一个实例,但是redis官方建议是最大1000个实例。存储足够大了。
3、ask和moved重定向的区别
重定向包括两种情况
a.若确定slot不属于当前节点,redis会返回moved。
b.若当前redis节点正在处理slot迁移,则代表此处请求对应的key暂时不在此节点,返回ask,告诉客户端本次请求重定向。
4、数据倾斜和访问倾斜的问题
倾斜导致集群中部分节点数据多,压力大。解决方案分为前期和后期:前期是业务层面提前预测,哪些key是热点,在设计的过程中规避。后期是slot迁移,尽量将压力分摊(slot调整有自动rebalance、reshard和手动)。
5、读写分离
redis cluster默认所有从节点上的读写,都会重定向到key对接槽的主节点上。
可以通过readonly设置当前连接可读,通过readwrite取消当前连接的可读状态。
注意:主从节点依然存在数据不一致的问题
Redis可用性
通过主从集群实现高可用,slave节点向master节点发送syn请求同步命令。master节点会通过bgsave命令创建rdb文件将数据以二进制形式存储其中,然后将文件分发给slave节点。
tips: 1.bgsave是创建了子线程工作,不影响主线程; 2.主从结构以线性链表部署,不要图状结构部署
Redis缓存失效问题
缓存一致性模型
查询信息时,先从缓存中获取信息;缓存中没有则从数据库中获取;将值塞到缓存。
缓存击穿
查询一个不存在的key,查询会直接落到数据库上。如果黑客用不存在的key查询,很可能搞垮数据库。
解决思路:查询之前先判断目标数据是否存在,不存在的直接忽略。将流量拦截于缓存和数据库之前。
这里使用布隆过滤器:
布隆过滤器
demo示例:
|
|
布隆过滤器优缺点
优点:
内存空间占用少
缺点:
布隆过滤器需要不断维护,带来新的工作
布隆过滤器并不能精准过滤。(布隆过滤器判定不存在,100%不存在,判断为存在,则可能不存在的。)理论上Hash计算值是有碰撞的(不同的内容hash计算出同样的值),导致不存在的元素可能
会被判断为存在
为了减少hash碰撞,可以将key用几个hash算法获取index值。然而布隆过滤器并非需要拦截所有的请求,只需要将缓存击穿控制在一定的量即可。
缓存雪崩
当大量的key在统一时间过期,而这时又有大量的访问key,请求落到数据上,导致数据库崩溃。
解决办法:
Semaphore信号量限流
J.U.C包重要的并发编程工具类,又称“信号量”,控制多个线程争抢许可。
核心方法
acquire:获取一个许可,如果没有就等待,
release:释放一个许可。
典型场景
1、代码并发处理限流;
示例:
|
|
容错降级
如果令牌被抢完(并发时还没来的及释放令牌),线程执行到这里时可以返回一个异常码。
redis集群方案
还有一种可能,如果redis key来不及删除,由于内存淘汰策略。会删除一些key,导致缓存失效。集群方案可以解决内存不足问题。
高并发下缓存不一致问题
根据缓存一致性模型:
查询信息时,a.1:先从缓存中获取信息;a.2:缓存中没有则从数据库中获取;a.3:将值塞到缓存。
更新数据时,b.1:更新数据库;b.2:删除缓存
如果查询和更新是两个线程,由于以上执行并非原子性,b.2可能会先于a.3执行。导致redis里面数据和数据库数据不一致。
解决方法
可以先将数据预热到redis中,去掉查询时存入redis的操作。再部署一个mysql服务,收集mysql日志。数据库数据发生变化的时候,通知缓存维护程序,把变化后的数据更新到到缓存里面。
关于数据库监听,阿里有一套开源框架 Canal ,可以监听mysql的数据变化。
Redis持久化
1.RDB快照:将数据以二进制形式写到文件中
2.AOF:将写命令以追加的形式写入到aof文件中
关于aof有下面几种形式:
a. redis没操作一次,写一次文件。优点是保证完整性,缺点是一致性会下降
b. 每秒钟将写命令写入到一个buffer中,当buffer中存满一定的数据,再写入到文件中(aof默认采用此种写入)
c.每次操作将写命令存入buffer中,之后再写入文件中
使用
默认是使用rdb恢复数据,如果开启aof,重启之后会加载aof文件恢复。当然生产环境上是混合使用。比如8点之前我使用rdb恢复,8点之后我使用aof恢复。
往期推荐
扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料
1.回复"java" 获取java电子书;
2.回复"python"获取python电子书;
3.回复"算法"获取算法电子书;
4.回复"大数据"获取大数据电子书;
5.回复"spring"获取SpringBoot的学习视频。
6.回复"面试"获取一线大厂面试资料
7.回复"进阶之路"获取Java进阶之路的思维导图
8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)
9.回复"总结"获取Java后端面试经验总结PDF版
10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)
11.回复"并发导图"获取Java并发编程思维导图(xmind终极版)
另:点击【我的福利】有更多惊喜哦。