`
xugangqiang
  • 浏览: 8297 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

读写分离的java redis 接口

阅读更多

 目的:为了spring上下文添加读写分离的接口,可以在启动后自动注入redis只读接口或可读写接口

 

1. 定义一个相关的functional interface - 在spring boot的启动类里面要用到(@EnableDynamicKeyValueServiceCreation)

@Retention(value = RetentionPolicy.RUNTIME)

@Import(KeyValueServiceRegister.class)

public @interface EnableDynamicKeyValueServiceCreation {

}

2. 定义只读接口和可读写接口
public interface KeyValueReadService { String get(String key); ...}

public interface KeyValueReadWriteService extends KeyValueReadService { void set(String key, String value); ..}

 

3. 实现类

public class RedisConfigInfo {

    private String hostName;

    private int port;

    private String password;

    private JedisPoolConfig poolConfig;

}

 

public abstract class AbstractRedisOperation {

    private final JedisPool jedisPool;

    public AbstractRedisOperation (RedisConfigInfo info) { jedisPool = ...;}

}

 

public class RedisReadServiceImpl extends AbstractRedisOperation implements KeyValueReadService {

 

    public RedisReadServiceImpl(RedisConfigInfo temp) {

        super(temp);

    }

 

    @Override

    public String get(String key) {

        return stringValueOps.get(key);

    }

}

 

4. 通过spring去获取redis的配置信息

@Component

public class KeyValueServiceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

 

    private static Logger logger = LoggerFactory.getLogger(KeyValueServiceRegister.class);

 

    private Map<String, BeanDefinition> beanDefinitionMap = null;

 

    @Override

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,

            BeanDefinitionRegistry registry) {

        if (beanDefinitionMap == null || beanDefinitionMap.isEmpty()) {

            logger.warn("beanDefinitions is empty");

            return;

        }

        String beanName;

        BeanDefinition beanDefinition;

        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {

            beanName = entry.getKey();

            beanDefinition = entry.getValue();

            registry.registerBeanDefinition(beanName, beanDefinition);

        }

 

    }

 

    @SuppressWarnings("rawtypes")

    @Override

    public void setEnvironment(Environment environment) {

        String prefix = environment.getProperty("prefix.keyvalue.cache", "kv.");

 

        Properties props = new Properties();

        MutablePropertySources propSrcs = ((AbstractEnvironment) environment).getPropertySources();

        StreamSupport.stream(propSrcs.spliterator(), false)

                .filter(ps -> ps instanceof EnumerablePropertySource)

                .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames())

                .flatMap(Arrays::<String>stream).filter(name -> name.startsWith(prefix)).forEach(

                        propName -> props.setProperty(propName, environment.getProperty(propName)));

        

        beanDefinitionMap = Collections

                .unmodifiableMap(KeyValueServiceHelper.buildBeanDefinitionMap(props));

    }

 

}

 

5. 根据配置信息构建bean

public class KeyValueServiceHelper {

 

    private static final String POSFIX_READ = ".r";

 

    private static final String POSFIX_WRITE = ".w";

 

    public static final Map<String, Properties> buildDataSourceMap(Properties prop) {

        if (prop == null || prop.isEmpty()) {

            return Collections.emptyMap();

        }

        Map<String, Properties> result = new HashMap<>();

        Set<String> keys = prop.stringPropertyNames();

        Properties temp;

        String dsName;

        for (String key : keys) {

            dsName = key;

            if (!isKeyValueServiceBeanName(key)) {

                dsName = removePosfix(key);

            }

            temp = result.get(dsName);

            if (temp == null) {

                temp = new Properties();

                result.put(dsName, temp);

            }

            temp.setProperty(key, prop.getProperty(key));

        }

        return result;

    }

 

    public static final boolean isKeyValueServiceBeanName(String str) {

        if (StringUtils.isBlank(str)) {

            return false;

        }

        return str.endsWith(POSFIX_READ) || str.endsWith(POSFIX_WRITE);

    }

 

    public static final String removePosfix(String str) {

        if (StringUtils.isBlank(str)) {

            return str;

        }

        int idx = str.lastIndexOf(".");

        if (idx == -1) {

            return str;

        }

        return str.substring(0, idx);

    }

 

    public static final String resolveBeanClassName(final String beanName,

            final String connectionStr) {

        if (StringUtils.isBlank(beanName)) {

            throw new IllegalArgumentException("bean name is blank");

        }

 

        if (StringUtils.isBlank(connectionStr)) {

            throw new IllegalArgumentException("connectionStr is blank");

        }

 

        if (!RedisConnectionHelper.isRedisConnectionString(connectionStr)) {

            throw new IllegalArgumentException("connectionStr is invalid");

        }

 

        if (beanName.endsWith(POSFIX_READ)) {

            return RedisReadServiceImpl.class.getName();

        }

        if (beanName.endsWith(POSFIX_WRITE)) {

            return RedisReadWriteServiceImpl.class.getName();

        }

        throw new IllegalArgumentException("beanName is invalid,should end with '.r' or '.w'");

    }

 

    public static final Map<String, BeanDefinition> buildBeanDefinitionMap(Properties props) {

        Map<String, Properties> cacheSources = buildDataSourceMap(props);

        if (cacheSources == null || cacheSources.isEmpty()) {

            return Collections.emptyMap();

        }

        BeanDefinition def;

        String beanName;

        String connectionStr;

        String beanClassName;

        Properties prop;

        RedisConfigInfo info;

        Map<String, BeanDefinition> beanMap =

                new HashMap<String, BeanDefinition>(cacheSources.size());

        for (Map.Entry<String, Properties> entry : cacheSources.entrySet()) {

            beanName = entry.getKey();

            prop = entry.getValue();

            connectionStr = prop.getProperty(beanName);

            if (!RedisConnectionHelper.isRedisConnectionString(connectionStr)) {

                continue;

            }

            info = RedisConnectionHelper.parseRedisConfigInfo(prop, beanName);

 

            def = new GenericBeanDefinition();

            beanClassName = KeyValueServiceHelper.resolveBeanClassName(beanName, connectionStr);

            def.setBeanClassName(beanClassName);

 

            def.getConstructorArgumentValues().addGenericArgumentValue(info);

            beanMap.put(beanName, def);

        }

        return beanMap;

    }

}

 

6. 如何使用

a. 在SpringBoot的启动类里面加上@EnableDynamicKeyValueServiceCreation

b. 配置文件里面加上读写分离的redis的配置信息 - 读的是.r结尾,可写的是.w结尾

c. 在需要只读redis的service里面, 直接注入(@KeyValueReadService (name=**.r)
d. 在需要读写redis的service里面, 直接注入(@KeyValueReadService (name=**.w)

 

0
1
分享到:
评论

相关推荐

    redis读写分离demo

    简单的redis读写分离demo 用的是依赖注入的方式,redis用的是主从复制

    Redis哨兵模式(sentinel)学习总结及部署记录(主从复制、读写分离、主从切换)

    Redis Sentinel提供了高可用性和自动化故障恢复能力,通过主从复制保证数据安全,读写分离提升系统性能,哨兵监控与故障转移保证服务稳定性。通过正确配置和部署,可以构建一个可靠的Redis集群,确保业务连续性。在...

    (重新整理版)redis的java客户端jedis 管理类代码 支持主从复制的自动选择和自动恢复,读/写分离

    上次传的代码, ...下载的朋友反映所有类都在一个文件看着有点乱,现重新整理了一下, 做成jar包使用 使用方法: 引用jar包,添加配置文件...* 2 可以选择读写分离功能,主写从读,默认不启用,都使用主服务进行所有操作

    阿里云Redis读写分离.pdf

    2018数据库直播大讲堂峰会-Redis专场阿里云Redis开发者午光对Redis读写分离进行介绍的PPT。

    Vue+SpringBoot+MySQL+redis课堂派前后端分离_redis集群读写分离

    在本项目中,Redis被用作集群实现读写分离,以提高系统的响应速度和数据处理能力。 首先,Vue.js是一个轻量级的前端JavaScript框架,它提供了组件化开发模式,使得开发者能够高效地构建用户界面。Vue的特点包括虚拟...

    最全redis线程池实现,Spring支持,redis Cluster线程池,主从Redis读写分离,sentenl读写分离等

    在本文中,我们将深入探讨如何在Java环境中,特别是在Spring框架下,实现全面的Redis线程池配置,包括Redis Cluster线程池、主从Redis的读写分离以及Sentinel的读写分离策略。 首先,我们要理解Redis线程池的重要性...

    JAVA数据库读写分离项目源码(MYSQL)

    5. **性能优化**:除了基本的读写分离,还可以考虑使用缓存(如Redis)、分页查询、索引优化等手段进一步提升系统性能。 通过深入研究这个项目源码,开发者不仅可以学习到读写分离技术,还能加深对SSM框架的理解,...

    springMVC读写分离

    在IT行业中,数据库的读写分离是一种常见的优化策略,它能有效地提高系统性能,尤其是在高并发环境下。SpringMVC作为Java Web开发中的一个强大框架,能够很好地支持这种架构设计。以下将详细介绍如何在SpringMVC项目...

    Redis使用教程,详解

    Jedis 是 Redis 官网首选的 Java 客户端开发包,通过 Jedis,我们可以在 Java 中使用 Redis。Jedis 的使用非常简单,首先需要引入相关的 jar 包,然后创建连接实例,最后使用 Jedis 操作 Redis。 Redis 的特点 ...

    Redis主从实现读写分离.doc

    在实际应用中,实现 Redis 的读写分离可以通过编程的方式,如在 Java 应用中使用 AOP(面向切面编程)来实现。例如,可以定义两个注解 `@JedisPoolSelector`,一个用于标记写操作,另一个用于标记读操作。然后创建一...

    redisCluster集群demo

    为了提高读取性能,可以配置主从复制,实现读写分离。 8. **注意点**: - 不支持某些命令:如`keys`、`sort`、`watch`等在集群模式下不完全支持,因为它们可能涉及到跨节点的操作。 - 集群的初始化和扩展需要谨慎...

    redis工具类以及redis 连接池配置

    创建jedis池配置实例,redis各种crud方法,包括使用主从同步,读写分离。工具类中包括存放hash表键值对,键值对以map的方式储存,删除键值对,永久存放键值对,设置过期时间,需要的直接去gitHab上看...

    redis+mysql使用学习

    5. **读写分离** - 读请求直接命中Redis,写请求通过Java应用程序处理MySQL,实现数据库读写的解耦。 6. **错误处理与回源** - 当Redis无数据或出现故障时,Java应用程序需要有回源机制,即直接查询MySQL并更新...

    spring-boot-mybatis多数据源读写分离实例

    MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 3. **多数据源**:在大型系统中,数据库通常会被分为多个数据源,每个...

    Redis如何实现数据库读写分离详解

    Redis是一种NoSQL的文档数据库,通过key-value的结构存储在内存中,Redis读的速度是110000次/s,写的速度是81000次/s,性能很高,使用范围也很广。Redis是一个key-value存储系统。和Memcached类似,为了保证效率,...

    Java开发中的Memcache原理及实现以及Redis的入门

    4. **主从复制与集群**: Redis支持主从复制,可以实现数据备份和读写分离。Redis Cluster是其官方提供的分布式解决方案,能自动将数据分散在多个节点上,实现水平扩展。 5. **高级功能**: Redis还提供了发布/订阅、...

    基于 gin+gorm+redis+mysql 读写分离的电子商城源码.zip

    总结起来,这个项目结合了Gin的Web开发能力、GORM的数据库操作便利性、Redis的高性能缓存和队列服务,以及MySQL的读写分离策略,构建了一个功能完善的电子商务平台。通过合理的架构设计和数据库优化,项目能够有效地...

    狂神说redis笔记

    主从复制允许将一台Redis服务器的数据复制到多个从服务器,实现数据的备份和读写分离,提高系统的可用性和可扩展性。 哨兵模式是Redis的一种高可用解决方案,它可以在主服务器故障时,自动将从服务器提升为新的主...

    redis从入门到精通

    4. **主从复制与集群**:通过主从复制机制,Redis支持数据的热备份以及读写分离,从而提高系统的可用性和负载能力;此外,Redis集群提供了自动分片功能,进一步增强了系统的扩展性。 5. **Lua脚本支持**:为了减少...

    spring 快速开发工具包,读写分离,多数据源,自动集成了mybatis,redis,seata等.zip

    这个工具包包含了多种功能模块,如读写分离、多数据源支持,以及对Mybatis、Sharding-JDBC、Redis和Seata等流行技术的集成。 1. **Spring框架**:Spring是Java开发中最广泛使用的应用框架之一,提供了依赖注入(DI...

Global site tag (gtag.js) - Google Analytics