java中使用redis2个库并支持Redis哈希表

news2024/11/25 11:48:16

一个redis实例,默认包含16个库,序号从0到15。在redis命令行中,可以用select 序号来切换。我最近在做的一个项目中,需要使用redis的2个库。一个是由其他子系统写入,web后端(java)只读取;数据读出来,处理后,再写入另一个redis库,供WEB前端请求。

同时,对Redis的操作支持哈希表。即运行过程中,可以修改哈希类型的键值。比如该值是一个Hash<String,Object>类型,赋值的时候,如果不存在指定元素,则添加;否则更新。这样做的好处是,该键值的元素,可由不同的步骤产生。比如写入的值,有些是同步产生的,有些是异步产生的,有先有后。

具体如下:

一、配置文件中设置redis信息

redis:
    db:
        db1:
            host: 10.0.1.8
            port: 6379
            database: 5
            timeout: 6000 # 单位是毫秒
        db2:
            host: 10.0.1.8
            port: 6379
            database: 6
            timeout: 6000 # 单位是毫秒

二、Configuration

1、创建一个RedisProperties类来读取配置文件信息

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {

    private Map<String, DatabaseProperties> db = new HashMap<>();

    public Map<String, DatabaseProperties> getDb() {
        return db;
    }
    public void setDb(Map<String, DatabaseProperties> db) {
        this.db = db;
    }

    public static class DatabaseProperties {
        private String host;
        private int port;
        private int database;
        private int timeout;

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }

        public int getDatabase() {
            return database;
        }

        public void setDatabase(int database) {
            this.database = database;
        }

        public int getTimeout() {
            return timeout;
        }

        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }
    }
}

2、Redis.config

里面声明了2个工厂,可供产生2个redisTemplate,分别对应不同的redis数据库。

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {

    @Bean(name = "redisConnectionFactory1")
    @Primary
    public RedisConnectionFactory redisConnectionFactory1(RedisProperties redisProperties) {
        return createConnectionFactory(redisProperties.getDb().get("db1"));
    }

    @Bean(name = "redisConnectionFactory2")
    public RedisConnectionFactory redisConnectionFactory2(RedisProperties redisProperties) {
        return createConnectionFactory(redisProperties.getDb().get("db2"));
    }

    private RedisConnectionFactory createConnectionFactory(RedisProperties.DatabaseProperties properties) {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(properties.getHost());
        config.setPort(properties.getPort());
        config.setDatabase(properties.getDatabase());

        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(properties.getTimeout()))
                .build();

        return new LettuceConnectionFactory(config, clientConfig);
    }

    @Bean(name = "redisTemplate1")
    @Primary
    public RedisTemplate<String, Object> redisTemplate1(
            @Qualifier("redisConnectionFactory1") RedisConnectionFactory factory) {
        return createRedisTemplate(factory);
    }

    @Bean(name = "redisTemplate2")
    public RedisTemplate<String, Object> redisTemplate2(
            @Qualifier("redisConnectionFactory2") RedisConnectionFactory factory) {
        return createRedisTemplate(factory);
    }

    private RedisTemplate<String, Object> createRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 配置具体的序列化方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }
}

三、如何使用两个 redis库?

思路是:
1)创建一个接口RedisService,声明各种对redis的操作
2)针对该接口,实现redisService1和redisService2,分别使用redisTemplate1和redisTemplate2
3)使用的时候,redisService1就是对应库1,redisService2对应库2

具体如下:

1、接口RedisService

import java.util.Map;
import java.util.Set;

public interface RedisService {
    Set<String> keys(String key);
    Set<String> keysAll();

    String get(String key);
    String get(String key, String hashKey);

    void set(String key,String value);

    void upsertArrayElements(String hashKey, Map<String, Object> newElements);

    Map<Object, Object> getArrayElements(String hashKey);

    boolean exists(String key);
    boolean hasKey(String key, String hashKey);
}

2、实现类1RedisService1Impl

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;

@Service("redisService1")
public class RedisService1Impl implements  RedisService{

    private final RedisHandler redisHandler;

    @Autowired
    public RedisService1Impl(@Qualifier("redisTemplate1") RedisTemplate<String, Object> redisTemplate) {
        this.redisHandler = new RedisHandler(redisTemplate);
    }

    @Override
    public Set<String> keys(String key){
        return redisHandler.keys(key);
    }
    @Override
    public Set<String> keysAll(){
        return redisHandler.keysAll();
    }

    @Override
    public String get(String key){
        return redisHandler.get(key);
    }
    @Override
    public String get(String key, String hashKey){
        return redisHandler.get(key,hashKey);
    }

    @Override
    public void set(String key,String value){
        redisHandler.set(key,value);
    }

    @Override
    public void upsertArrayElements(String hashKey, Map<String, Object> newElements) {
        // 对于每个新元素,如果它不存在于哈希表中,则添加它;如果它已经存在,则覆盖它。
        redisHandler.upsertArrayElements(hashKey,newElements);
    }
    @Override
    public Map<Object, Object> getArrayElements(String hashKey) {
        return redisHandler.getArrayElements(hashKey);
    }

    @Override
    public boolean exists(String key){
        return redisHandler.exists(key);
    }
    @Override
    public boolean hasKey(String key, String hashKey){
        return redisHandler.hasKey(key,hashKey);
    }
}

注意代码中,声明使用redisTemplate1

    @Autowired
    public RedisService1Impl(@Qualifier("redisTemplate1") RedisTemplate<String, Object> redisTemplate) {
        this.redisHandler = new RedisHandler(redisTemplate);
    }

3、实现类2RedisService2Impl

基本上与RedisService1Impl没有什么区别,只是对应的redisTemplate不一样。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;

@Service("redisService2")
public class RedisService2Impl implements  RedisService{

    private final RedisHandler redisHandler;

    @Autowired
    public RedisService2Impl(@Qualifier("redisTemplate2") RedisTemplate<String, Object> redisTemplate) {
        this.redisHandler = new RedisHandler(redisTemplate);
    }

    @Override
    public Set<String> keys(String key){
        return redisHandler.keys(key);
    }
    @Override
    public Set<String> keysAll(){
        return redisHandler.keysAll();
    }

    @Override
    public String get(String key){
        return redisHandler.get(key);
    }
    @Override
    public String get(String key, String hashKey){
        return redisHandler.get(key,hashKey);
    }

    @Override
    public void set(String key,String value){
        redisHandler.set(key,value);
    }

    @Override
    public void upsertArrayElements(String hashKey, Map<String, Object> newElements) {
        // 对于每个新元素,如果它不存在于哈希表中,则添加它;如果它已经存在,则覆盖它。
        redisHandler.upsertArrayElements(hashKey,newElements);
    }
    @Override
    public Map<Object, Object> getArrayElements(String hashKey) {
        return redisHandler.getArrayElements(hashKey);
    }

    @Override
    public boolean exists(String key){
        return redisHandler.exists(key);
    }
    @Override
    public boolean hasKey(String key, String hashKey){
        return redisHandler.hasKey(key,hashKey);
    }
}

4、公共Redis操作类RedisHandler

import com.landtool.server.modules.utils.JsonUtil;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;

@Component
public class RedisHandler {

    private RedisTemplate<String, Object> redisTemplate;

    public RedisHandler(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 是否存在指定key
     */
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 是否存在键
     */
    public boolean hasKey(String key, String hashKey) {
        assert key != null && hashKey != null;
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        return hashOperations.hasKey(key, hashKey);
    }

    /**
     * 获取所有key
     */
    public Set<String> keys(String key) {
        assert key != null;
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        return hashOperations.keys(key);
    }

    public Set<String> keysAll() {
        return redisTemplate.keys("*");
    }

    public String get(String key) {
        Object value = redisTemplate.opsForValue().get(key);
        return value != null ? value.toString() : null;
    }
    public String get(String key, String hashKey) {
        assert key != null && hashKey != null;
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        String json = null;
        try {
            json = JsonUtil.toJsonString(hashOperations.get(hashKey, key));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return json;
    }

    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public void upsertArrayElements(String hashKey, Map<String, Object> newElements) {
        // 对于每个新元素,如果它不存在于哈希表中,则添加它;如果它已经存在,则覆盖它。
        redisTemplate.opsForHash().putAll(hashKey, newElements);
    }

    public Map<Object, Object> getArrayElements(String hashKey) {
        return redisTemplate.opsForHash().entries(hashKey);
    }

    /**
     * 删除数据
     */
    public Long delete(String key, String... hashKeys) {
        assert key != null && hashKeys != null;
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        return hashOperations.delete(key, hashKeys);
    }
}

四、调用RedisService

@Autowired
@Qualifier("redisService1")
RedisService redisService;

@Autowired
@Qualifier("redisService2")
RedisService redisService2;

redisService.***,使用库1
redisService2.***,使用库2

五、操作哈希表

private static final String REDIS_CHECK_LINK = "check_link";
public void freshCheckLink() {
    Map<String, Object> links = new HashMap<>();

    //nce
    getNce();

    //outer-api
    links.put("outerApi",某值);

    redisService2.upsertArrayElements(REDIS_CHECK_LINK,links);
}
private void getNce() {
    AtomicLong myCount = new AtomicLong();
    CompletableFuture.supplyAsync(() -> {
		。。。
    }).thenAccept(count -> {
	    Map<String, Object> links = new HashMap<>();
	    links.put("nce",myCount.get() >= 0);
	    redisService2.upsertArrayElements(REDIS_CHECK_LINK,links);
    });
}
private void setNceStatus(boolean status){

}

这样子,键名为“check_link”的结构如下:
在这里插入图片描述

六、小结

Redis使用多个库有现实意义。在我这个项目中,是为了避免冲突。库1由其他子系统频繁写入,而库2则是将数据从库1读取、分析、整理后产生的结果。web前端向后端请求数据,后端直接从结果从库2读出,避免了每个请求都分析、整理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1043048.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

瑞芯微RK3568|SDK开发之Kernel编译

1. Kernel手动编译 1.1 kernel查询帮助 使用./build.sh -h kernel查看kernel的详细编译命令如下所示。 图1.1编译内核 上图表示&#xff0c;单独编译kernel固件分为三步&#xff0c;进入kernel目录&#xff0c;选择默认配置文件&#xff0c;编译镜像。 1.2 kernel…

多家快递公司物流信息批量查询方法及操作说明

在网购时代&#xff0c;快递单号的查询和管理成了一个重要的问题。尤其是对于需要处理大量快递单号的人来说&#xff0c;一个高效、便捷的查询工具至关重要。本文将介绍如何使用“固乔快递查询助手”软件&#xff0c;快速、准确地查询多家不同快递公司的快递单号&#xff0c;并…

最新白皮书:软件定义的硬件打开通往高性能数据加速的大门

在众多行业的数字化转型过程中&#xff0c;基于硬件的数据处理加速是构建高性能、高效率智能系统的关键之处&#xff0c;因而市场上出现了诸如FPGA、GPU和xPU等许多通用或者面向特定应用&#xff08;如NPU&#xff09;的硬件加速器。尽管它们的性能和效率都高于通用处理器&…

基于R的linkET包qcorrplot可视化Mantel test相关性网络热图分析correlation heatmap

写在前面 需求是对瘤胃宏基因组结果鉴定到的差异菌株与表观指标、瘤胃代谢组、血清代谢组、牛奶代谢组中有差异的部分进行关联分析&#xff0c;效果图如下&#xff1a; 数据准备 逗号分隔的csv格式文件&#xff0c;两个表格&#xff0c;一个是每个样本对应的表观指标数据&…

工业交换机常见的故障有哪些?

通常情况下&#xff0c;工业交换机出现故障可以分为两类&#xff1a;软件性能故障和硬件物理故障。软性能故障通常指工业交换机在研发设计阶段出现的问题。 物理层故障主要指交换机本身的硬件故障以及连接交换机的物理线路故障。安防专用工业交换机的交换是根据通信双方传输信…

构建智能客服知识库,优化客户体验不是难题!

在当今快节奏的商业环境中&#xff0c;客户都希望得到及时个性化的支持&#xff0c;拥有一个智能客服知识库对于现代企业至关重要。智能客服知识库是一个集中存储、组织和访问与客户服务互动相关的信息的综合性知识库。它为企业提供了全面的知识来源&#xff0c;使他们能够为客…

PHP循环获取Excel表头字母A-Z,当超过时输出AA,AB,AC,AD······

PHP循环获取Excel表头字母A-Z&#xff0c;当超过时输出AA,AB,AC,AD PHP循环生成Excel的列字母表 $count_num 26 * 27; $letter A; $arr []; while($count_num--){$arr[] $letter;$letter; }结果如下&#xff1a; 转为JSON更为直观&#xff1a; ["A","B&…

MySQL 8 0 填坑历险之安装与基本用户权限

MySQL 8.0 填坑历险之安装 MySQL 是当下流行的关系型数据库&#xff0c;搜掠了各种文章&#xff0c;多少有些偏差&#xff0c;为此来分享下我的经历&#xff1b; 安装环境 环境版本备注Ubuntu 18.0418.04.6 LTS (Bionic Beaver)LinuxKernel5.4.0-42-genericMySQL 8.0.23mysq…

上海亚商投顾:沪指震荡调整 减肥药、华为概念股持续活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡调整&#xff0c;上证50午后一度跌近1%&#xff0c;券商、保险等权重板块走势低迷。 华为概…

大咖共探AGI时代机遇,腾讯云助力大模型规模化应用提速

引言 2023 年&#xff0c;科技圈的“顶流”莫过于大模型。自 ChatGPT 的问世拉开大模型与生成式 AI 产业的发展序幕后&#xff0c;国内大模型快速跟进&#xff0c;已完成从技术到产品、再到商业的阶段跨越&#xff0c;并深入垂直行业领域。 新技术的爆发&#xff0c;催生新的应…

唤醒手腕 2023年 B 站课程 Golang 语言详细教程笔记(更新中)

0001、1000集GO语言Flag毒誓 唤醒手腕UP猪Pig目标花费1000集进行讲解Go语言视频学习教程&#xff08;有趣的灵魂&#xff0c;适合小白&#xff0c;不适合巨佬&#xff09;&#xff0c;从2023年3月19日开始&#xff0c;将会一直每天更新&#xff0c;准备在2024年5月1日之前更新…

(主)9.26锁存器状态机方法、题解大综合(加码加码加码)

触发器 D D锁存器就是在有时钟信号时&#xff0c;D信号是啥&#xff0c;Q就是啥&#xff0c;并且在时钟信号消失时&#xff0c;锁存住消失前一刻的信号状态 主从D锁存器中&#xff0c;D信号是主锁存器的输入信号&#xff0c;主锁存器的信号是从锁存器的输入信号 用D实现的电…

苹果电脑专业的条形码工具iBarcoder:助力高效条形码生成,提升工作效率

iBarcoder for mac是Mac os平台上的一款优秀条码生成软件。它可以帮助用户建立不同类型的条形码&#xff0c;并允许用户设计并打印自己的条码标签&#xff0c;创建条码图形的零售包装、书籍、贴纸等。 在iBarcoder中&#xff0c;用户可以方便地创建专业的条形码标签&#xff0…

Linux服务器安装Anaconda 配置远程jupyter lab使用虚拟环境

参考的博客&#xff1a; Linux服务器安装Anaconda 并配置远程jupyter lab anaconda配置远程访问jupyter&#xff0c;并创建虚拟环境 理解和创建&#xff1a;Anaconda、Jupyterlab、虚拟环境、Kernel 下边是正文了。 https://www.anaconda.com/download是官网网址&#xff0c;可…

C/C++进程线程超详细详解

目录 前言 一、进程基础 1.进程概念 2.进程特征 3.进程状态&#xff08;如图清晰可见&#xff09; 4&#xff0c;进程的标识 实例代码如下&#xff1a; 5.进程的种类 实例shell脚本程序如下: 二、进程API 1.创建子进程 实例代码如下&#xff1a; 2.exec函数族 函数…

ptmalloc源码分析 - free()函数的实现(10)

目录 一、步骤1-标记MMAP分配的使用munmap_chunk释放 二、步骤2-释放的是小块内存&#xff0c;则chunk放入fastbin 三、步骤3-如果不是MMAP分配&#xff0c;则释放到unsorted bins 四、步骤4-如果nextchunk 就是Top chunk&#xff0c;则直接扩容Top chunk 五、步骤5-如果释…

分享从零开始学习网络设备配置--任务4.1 IPv6地址的基本配置

任务描述 某公司构建了互联互通的办公网&#xff0c;需要不断扩大网络规模。网络管理员小赵决定采用IPv6的地址&#xff0c;满足公司网络规模的未来发展。 由于IPv4地址耗尽及IPv4地址区域分配不均衡&#xff0c;成为运营商必须面临的一个问题。另外随着互联网的商业化&#…

【python】将python脚本打包成可执行的.exe文件 推荐使用auto-py-to-exe

将python脚本打包成可执行的exe文件 1.不推荐使用网上流行的打包程序&#xff0c;主要是有以下几点&#xff0c;一、cx_freeze与Pyinstaller都是命令行的形 式&#xff0c;且对于Pyinstaller的打包常常需要打包完成后&#xff0c;再修改打包后的原路径&#xff0c;二、非可视…

vue wangEditor富文本编辑器 默认显示与自定义工具栏配置

1.vue 显示wangEditor富文本编辑器 <template><div style"border: 1px solid #ccc;"><Toolbar style"border-bottom: 1px solid #ccc" :editor"editor" :defaultConfig"toolbarConfig" :mode"mode"/><…

Vue-diff算法和双向数据绑定原理

Vue–diff算法 我们提到了vue–diff算法之前先说一下关于vue的编译过程 一、Vue的编译过程主要分为以下的几个步骤&#xff1a; 1&#xff0c;解析模板&#xff1a;Vue会将模板解析语法树AST&#xff0c;并且对其中的指令和元素进行标记。 2&#xff0c;优化静态内容&#…