实战1|使用分布式缓存Redis实现热点资源顺序访问

应用现状

在传统单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLock或synchronized)进行互斥控制。这种Java提供的原生锁机制可以保证在同一个Java虚拟机进程内的多个线程同步执行,避免出现无序现象。

但在互联网场景,如商品秒杀中,随着整个系统的并发飙升,需要多台机器并发运行,假设此时两个用户的请求同时到来,但落在了不同的机器上,虽然这两个请求是可以同时执行,但是因为两个机器运行在两个不同的Java虚拟机里面,他们加的锁只对属于自己Java虚拟机里面的线程有效,对于其他Java虚拟机的线程是无效的。因此,Java提供的原生锁机制在多机部署场景下失效了,这是因为两台机器加的锁不是同一个锁(两个锁在不同的Java虚拟机里面),这样便会出现库存超卖的现象。

解决方案

基于存在的现状,我们只要保证两台机器加的锁是同一个锁,用加锁的方式对某种资源进行顺序访问控制。这就需要分布式锁登场了。

分布式锁的思路是:在整个系统提供一个全局、唯一的获取锁的“东西”,然后每个系统在需要加锁时,都去问这个“东西”拿到一把锁,这样不同的系统拿到的就可以认为是同一把锁。

当前分布式加锁主要有三种方式:(磁盘)数据库、缓存数据库、Zookeeper。

使用分布式缓存服务中Redis类型的缓存实例实现分布式加锁,有几大优势:

1、加锁操作简单,使用SET、GET、DEL等几条简单命令即可实现锁的获取和释放。

2、性能优越,缓存数据的读写优于磁盘数据库与Zookeeper。

3、可靠性强,分布式缓存Redis有主备和集群实例类型,避免单点故障。

对分布式应用加锁,能够避免出现库存超卖及无序访问等现象,实战:如何使用Redis对分布式应用加锁。

前提条件

1、已购买弹性云服务器(ECS)且系统类型为Windows。

2、在ECS上安装JDK1.8以上版本和Eclipse,下载jedis客户端(点此处直接下载jar包)。

3、已购买分布式缓存Redis缓存实例且和ECS选择相同虚拟私有云、子网以及安全组。

操作步骤

1、在ECS上运行Eclipse,创建一个java工程,为示例代码分别创建一个分布式锁实现类DistributedLock.java和测试类CaseTest.java,将jedis客户端作为libs引用到工程中。

2、将分布式缓存Redis缓存实例的连接地址、端口以及连接密码配置到分布式锁实现类DistributedLock.java示例代码文件中。在DistributedLock.java中,host及port配置为实例的连接地址及端口号,在getLockWithTimeout、releaseLock方法中需配置passwd值为实例访问密码。

3、将测试类CaseTest中加锁部分注释掉,变成无锁情况。

4、编译及运行无锁的类,运行结果是抢购无序的。

5、取消测试类CaseTest中注释的加锁内容,编译并运行得到有序的抢购。

详细步骤及代码详情请参考:使用DCS实现热点资源顺序访问

实战3|使用分布式缓存Redis快速搭建高性能缓存服务

华为云分布式缓存服务DCS,提供单机、主备、集群等丰富的缓存类型,满足用户高读写性能及快速数据访问的业务诉求。华为云控制台提供一键式创建缓存实例,以及丰富的实例管理操作,帮助用户省去运维烦恼。如何创建并连接一个Redis缓存实例为例,带大家快速上手分布式缓存技术。

准备环境

登录华为云控制台。在控制台页面中选择“网络> 虚拟私有云”,创建VPC(虚拟私有云),用于对缓存实例进行安全网络隔离。

在控制台页面中选择“计算> 弹性云服务器”,创建一台弹性云服务器(ECS),用于下载客户端连接缓存实例。

 创建实例

登录华为云控制台,选择“应用服务> 分布式缓存服务”,选择计费模式。

在DCS总览页面,单击“购买缓存实例”,选择实例配置,创建实例。

连接缓存实例

缓存实例创建成功后,在DCS实例管理页找到实例连接地址和端口。

登录ECS,下载和安装客户端。

连接实例。

读写缓存数据。

上述就是创建并连接一个Redis缓存实例为例的教程,快来创建一个高性能的服务吧。

了解详情:点击此处前往

实战2|使用分布式缓存Redis实现排行榜功能

场景介绍

在网页和APP中常常需要用到榜单的功能,对某个key-value的列表进行降序显示。当操作和查询并发大的时候,使用传统数据库就会遇到性能瓶颈,造成较大的时延。

使用分布式缓存服务(DCS)的Redis版本,可以实现一个商品热销排行榜的功能。它的优势在于:

数据保存在缓存中,读写速度非常快。

提供字符串(String)、链表(List)、集合(Set)、哈希(Hash)等多种数据结构类型的存储。

实践指导

1、准备一台弹性云服务器(ECS),选择Windows系统类型。

2、在ECS上安装JDK1.8以上版本和Eclipse,下载jedis客户端(点此处直接下载jar包)。

3、在华为云控制台购买DCS缓存实例。注意和ECS选择相同虚拟私有云、子网以及安全组。

4、在ECS上运行Eclipse,创建一个java工程,为示例代码创建一个productSalesRankDemo.java文件,并将jedis客户端作为library引用到工程中。

5、将DCS缓存实例的连接地址、端口以及连接密码配置到示例代码文件中。

6、编译并运行得到结果。

代码示例参考:点击这里前往代码示例

运行结果

编译并运行以上Demo程序,运行结果:点击这里前往运行结果

实战4|如何发现和处理大Key和热Key

如何处理优化大Key和热Key

大Key

进行大Key拆分,分为以下几种场景:

该对象为String类型的大Key:可以尝试将对象分拆成几个Key-Value, 使用MGET或者多个GET组成的pipeline获取值,分拆单次操作的压力,对于集群来说可以将操作压力平摊到多个分片上,降低对单个分片的影响。

该对象为集合类型的大Key,并且需要整存整取:在设计上严格禁止这种场景的出现,因为无法拆分。有效的方法是将该大Key从Redis去除,单独放到其余存储介质上。

该对象为集合类型的大Key,每次只需操作部分元素:将集合类型中的元素分拆。以Hash类型为例,可以在客户端定义一个分拆Key的数量N,每次对HGET和HSET操作的field计算哈希值并取模N,确定该field落在哪个Key上,实现上类似于Redis Cluster的计算slot的算法。

将大Key单独转移到其余存储介质。

无法拆分的大Key建议使用此方法,将不适用Redis能力的数据存至其它存储介质,如SFS或者其余NoSQL数据库,并在Redis中删除该大Key。

注意:禁止使用DEL直接删除大Key,可能会造成Redis阻塞,甚至主备倒换。

合理设置过期时间并对过期数据定期清理。

合理设置过期时间,避免历史数据在Redis中大量堆积。由于Redis的惰性删除策略,过期数据可能并不能及时清理,如果发现Redis过期Key清理较慢,建议配置过期Key扫描

热Key

使用读写分离。

如果热Key主要是读流量较大,则可以在客户端配置读写分离,降低对主节点的影响。还可以增加多个副本以满足读需求,但是备机较多也有相应的影响,华为云DCS主备节点之间使用的是星型复制,即所有的备节点都直接和主节点保持同步,这样能保证备节点之间相互独立,且复制延迟较小。缺点是在备节点数量较多的情况下,主节点的CPU和网络负载会较高。

使用客户端缓存/本地缓存。

该方案需要提前了解业务的热点Key有哪些,设计客户端/本地和远端Redis的两级缓存架构,热点数据优先从本地缓存获取,写入时同时更新,这样能够分担热点数据的大部分读压力。缺点是需要修改客户端架构和代码,改造成本较高。

设计熔断。

热Key极易造成缓存击穿,高峰期请求都直接透传到后端数据库上,从而导致业务雪崩。因此热Key的优化一定需要设计系统的熔断,在发生击穿的场景下进行限流和服务下调,保护系统的可用性。

如何发现大Key和热Key

方法
说明

使用分布式缓存服务DCS自带的大Key和热Key分析工具进行分析


请参考分析Redis实例大Key和热Key

通过redis-cli的bigkeys和hotkeys参数查找大Key和热Key

1、Redis-cli提供了bigkeys参数,能够使redis-cli以遍历的方式分析Redis实例中的所有Key,并返回Key的整体统计信息与每个数据类型中Top1的大Key,bigkeys仅能分析并输入六种数据类型(STRING、LIST、HASH、SET、ZSET、STREAM),命令示例为:redis-cli -h <实例的连接地址> -p <端口> -a <密码> --bigkeys。

2、自Redis 4.0版本起,redis-cli提供了hotkeys参数,可以快速帮您找出业务中的热Key,该命令需要在业务实际运行期间执行,以统计运行期间的热Key。命令示例为:redis-cli -h <实例的连接地址> -p <端口> -a <密码> --hotkeys。热Key的详情可以在结果中的summary部分获取到。

通过Redis命令查找大Key

如果有已知的大Key模式,例如知道其前缀为huaweicloud:msg:test,那么可以通过一个程序,SCAN符合该前缀的Key,然后通过查询成员数量和查询Key大小的相关命令,来判断具体的大Key。

1、查询成员数量的相关命令:LLEN,HLEN,XLEN,ZCARD,SCARD

2、查询Key占用内存大小的命令:DEBUG OBJECT,MEMORY USAGE

注意:

该方法会大量消耗计算资源,请知晓并评估其风险,不要在业务压力较大的实例使用该方法,否则可能会对正常业务造成影响。

通过redis-rdb-tools工具找出大Key

redis-rdb-tools是分析Redis RDB快照文件的开源工具。可以根据需求自定义分析Redis实例中所有Key的内存占用情况。

使用此方法需要在分布式缓存服务DCS实例备份与恢复页签中导出实例的rdb文件

注意:

该方法时效性相较于在线分析来说较差,优势在于完全不影响现有业务。

分布式缓存服务教程视频

分布式缓存服务DCS

04:53

分布式缓存服务DCS

分布式缓存服务DCS

03:40

分布式缓存服务DCS

分布式缓存服务DCS

04:16

分布式缓存服务DCS