Redis实践(4.3)SpringBoot 读模式的负载均衡

Redis
placeholder image
admin 发布于:2023-05-28 08:24:00
阅读:loading

前文中使用SpringBoot Data Redis项目集成了Redis的主从架构接入,本篇主要来测试一下整合后从项目中使用自定义的工具类操作redis相关的API,实现操作Redis读模式的负载均衡。前篇示例中分别提供了注解@Resource注入的形式获取RedisTemplate类型,但是获取到固定的是某台服务器的连接模板对象,在使用过程中一旦定义则每次请求均来自一个模块,理论上可以通过模块功能代码的形式来实现压力复杂。另外一种则是本文使用的工具类来实现读取数据的负载均衡(前文中所述写模式只有一台服务器所以不存在负载均衡),详见下文。

1.RedisUtils

package cn.chendd.redis.utils;

import ...;

/**
 * RedisUtils工具类
 *
 * @author chendd
 * @date 2023/5/19 22:00
 */
public final class RedisUtils {

    private RedisUtils() {

    }

    @SuppressWarnings("unchecked")
    public static <T> RedisTemplate<String , T> getWriteRedisTemplate() {
        return SpringBeanFactory.getBean(RedisConstants.WRITE_REDIS_TEMPLATE , RedisTemplate.class);
    }

    public static StringRedisTemplate getWriteStringRedisTemplate() {
        return SpringBeanFactory.getBean(RedisConstants.WRITE_STRING_REDIS_TEMPLATE , StringRedisTemplate.class);
    }

    private static final AtomicLong READ_STRING_REDIS_TEMPLATE = new AtomicLong(0);

    private static final AtomicLong READ_REDIS_TEMPLATE = new AtomicLong(0);

    @SuppressWarnings("unchecked")
    public static <T> RedisTemplate<String, T> getReadRedisTemplate() {
        long value = READ_REDIS_TEMPLATE.addAndGet(1L);
        if (value % 2 == 0) {
            return SpringBeanFactory.getBean(RedisConstants.READ1_REDIS_TEMPLATE , RedisTemplate.class);
        } else {
            return SpringBeanFactory.getBean(RedisConstants.READ2_REDIS_TEMPLATE , RedisTemplate.class);
        }
    }

    public static StringRedisTemplate getReadStringRedisTemplate() {
        long value = READ_STRING_REDIS_TEMPLATE.addAndGet(1L);
        if (value % 2 == 0) {
            return SpringBeanFactory.getBean(RedisConstants.READ1_STRING_REDIS_TEMPLATE , StringRedisTemplate.class);
        } else {
            return SpringBeanFactory.getBean(RedisConstants.READ2_STRING_REDIS_TEMPLATE , StringRedisTemplate.class);
        }
    }

}

【说明】

(1)基数次请求将获得Read1的实例,偶数次获得Read2的实例,也可以修改为随机获得实例;也可以换成随机模式,随机获得一个读模式的实例;

(2)示例代码写的比较随意无注释;

2.测试代码

package cn.chendd.redis;

/**
 * Redis读负载均衡测试【循环10次,观察每次获取到的参数信息】
 *
 * @author chendd
 * @date 2023/5/19 16:39
 */
public class ReadisReadLoadBalanceTest extends BaseTest {

    @Test
    public void lbRedisTemplate() {
        for (int i = 1 ; i <= 10 ; i++) {
            RedisTemplate redisTemplate = RedisUtils.getReadRedisTemplate();
            LettuceConnectionFactory read = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
            assert read != null;
            System.out.println(MessageFormat.format("read redisTemplate {0} host = {1} , port = {2}" , i , read.getHostName(), read.getPort()));
        }
    }

    @Test
    public void lbStringRedisTemplate() {
        for (int i = 1 ; i <= 10 ; i++) {
            StringRedisTemplate stringRedisTemplate = RedisUtils.getReadStringRedisTemplate();
            LettuceConnectionFactory read = (LettuceConnectionFactory) stringRedisTemplate.getConnectionFactory();
            assert read != null;
            System.out.println(MessageFormat.format("read stringRedisTemplate {0} host = {1} , port = {2}" , 
                 i , read.getHostName(), read.getPort()));
        }
    }
}

【说明】

(1)示例分别是对RedisTemplate和StringRedisTemplate两个类型测试,获得对应类型的实例放置在循环内部,表示多次获取将轮询从多个读模式示例中按顺序获取实例;

(2)正常情况应在循环外部获取实例,避免每次请求都执行对象赋值;

(3)上述示例获得的RedisTemplate类型实例将交替输出Read1和Read2不同的对象信息;

3.运行输出

验证读模式负载均衡.gif

【说明】

(1)示例代码有两个函数分别是验证RedisTemplate和StringRedisTemplate,均已经执行;

(2)在循环内部多次获取的RedisTemplate实例,交替获得不同的实例,若将调用get相关API将有负载均衡的效果;

(3)实际应用中若在循环内部干活时,不要把获得RedisTemplate实例放置在循环内部,避免每次循环都要去获取实例;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区