Java连接Redis

news2024/12/25 2:37:04

Jedis是Redis官方推荐的Java连接开发工具。

api:https://tool.oschina.net/apidocs/apidoc?api=jedis-2.1.0

一、 导入包

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

二、创建工具类 RedisUtil

package com.utils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisUtil {
    //Redis服务器IP
    private static String ADDR = "127.0.0.1";

    //Redis的端口号
    private static int PORT = 6379;

    //访问密码
    private static String AUTH = "123456";

    //可用连接实例的最大数目,默认值为8;
    //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 1024;

    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 200;

    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 10000;

    private static int TIMEOUT = 10000;

    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;

    private static JedisPool jedisPool = null;

    //初始化redis连接池
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(MAX_IDLE);
        config.setMaxWaitMillis(MAX_WAIT);
        config.setTestOnBorrow(TEST_ON_BORROW);
        //配置,IP,端口,超时时间,密码
        jedisPool = new JedisPool(config,ADDR,PORT,TIMEOUT,AUTH);
    }

    //获取Jedis实例
    public synchronized static Jedis getJedis(){
        if(jedisPool!=null){
            Jedis jedis = jedisPool.getResource();
            return jedis;
        }else{
            return null;
        }
    }
    //释放jedis资源
    public static void returnResource(Jedis jedis){
        if(jedis!=null){
            jedisPool.returnResource(jedis);
        }
    }

}

三、在测试类中测试

测试代码

 //redis存储字符串 string
    @Test
    public void testString(){
        jedis.select(2);
        jedis.set("name","laowang");
        jedis.set("name","laoli");
        System.out.println(jedis.get("name"));
        jedis.set("age","18");
        System.out.println(jedis.get("age"));
        //拼接
        jedis.append("name"," is my love");
        System.out.println(jedis.get("name"));
        //删除
        jedis.del("age");
        System.out.println(jedis.get("age"));
        //设置多个键值对
        jedis.mset("sname","laozhang","sage","28","qq","11223344");
        jedis.incr("sage");//加1操作
        System.out.println(jedis.get("sname")+"-"+jedis.get("sage")+"-"+jedis.get("qq"));
    }

    //redis操作hash--java里面操作Map map<String,String>
    @Test
    public void testMap(){
        Map<String,String> map = new HashMap<>();
        map.put("name","laozhang");
        map.put("age","16");
        map.put("qq","123456");
        jedis.hmset("user",map);

        List<String> rsmap = jedis.hmget("user", "name", "age", "qq");
        System.out.println(rsmap);

        //删除map中某一个键
        jedis.hdel("user","age");
        System.out.println(jedis.hmget("user","age"));//删除了age的key 获取null
        System.out.println(jedis.hlen("user"));//返回user的键中还有几个value
        System.out.println(jedis.exists("user"));//是否存在某个key
        System.out.println(jedis.hkeys("user"));//返回map对象中所有的key
        System.out.println(jedis.hvals("user"));//返回map对象中所有的value

        Iterator<String> iterator = jedis.hkeys("user").iterator();
        while (iterator.hasNext()){
            String key = iterator.next();
            System.out.println(key+":"+jedis.hmget("user",key));
        }
    }

    /**
     * jedis操作List-- java里面操作的是List<String>
     */
    @Test
    public void testList() {
        //开始前,先移除所有的内容
        jedis.del("java framework");
        System.out.println(jedis.lrange("java framework", 0, -1));
        //先向key java framework中存放三条数据
        jedis.lpush("java framework", "spring");//redis的list类型 每个元素都是string
        jedis.lpush("java framework", "struts");
        jedis.lpush("java framework", "hibernate");
        //再取出所有数据jedis.lrange是按范围取出,
        // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有
        System.out.println(jedis.lrange("java framework", 0, -1));

        jedis.del("java framework");
        jedis.rpush("java framework", "spring");
        jedis.rpush("java framework", "struts");
        jedis.rpush("java framework", "hibernate");
        System.out.println(jedis.lrange("java framework", 0, -1));
    }

    /**
     * jedis操作Set -- 在java里面返回的Set<String>或List<String>
     * (例如System.out.println(jedis.srandmember("user1"));时返回的就是一个List<String>)
     *  但是set类型本身是一个无序+不重复的list == java Set
     */
    @Test
    public void testSet() {
        //添加
        jedis.sadd("user1", "liuling");
        jedis.sadd("user1", "xinxin");
        jedis.sadd("user1", "ling");
        jedis.sadd("user1", "zhangxinxin");
        jedis.sadd("user1", "who");
        //移除其中一个元素
        jedis.srem("user1", "who");
        System.out.println(jedis.smembers("user1"));//获取所有加入的value
        System.out.println(jedis.sismember("user1", "who"));//判断 who 是否是user集合的元素
        //随机元素
        System.out.println(jedis.srandmember("user1"));
        System.out.println(jedis.scard("user1"));//返回集合的元素个数
    }

    //jedis操作zset -- java返回的是 Set<String> 排序+不重复的list 有点像 java TreeSet
    @Test
    public void test() throws InterruptedException {
        //如果要实现有序的集合,可以考虑使用list来排序(不去重)
        //注意,此处的rpush和lpush是List的操作。是一个双向链表(但从表现来看的)
        jedis.del("a");//先清除数据,再加入数据进行测试
        jedis.rpush("a", "1");
        jedis.lpush("a", "6");
        jedis.lpush("a", "3");
        jedis.lpush("a", "9");
        System.out.println(jedis.lrange("a", 0, -1));// [9, 3, 6, 1]
        System.out.println(jedis.sort("a")); //[1, 3, 6, 9]  //输入排序后结果

        //使用zset类型实现有序集合去重
        //使用zadd命令 成绩排序 升序
        jedis.zadd("scoreList",100.0,"张三");
        jedis.zadd("scoreList",70.0,"李四");
        jedis.zadd("scoreList",85.5,"王朝");
        jedis.zadd("scoreList",100.0,"马汉");
        jedis.zadd("scoreList",90.0,"马汉");
        //展示全部
        System.out.println(jedis.zrange("scoreList",0,-1));

    }

四、Redis类型的使用场景

1、Redis 字符串(String)
  • 典型应用场景:

  • 1.作为缓存 -- 数据分两类冷数据与热数据,热数据表示经常使用的时常发生变化的数据但是对数据一致性要求不高的数据,如一个视频的点击量,某文件的浏览次数,某商品的日月销量,系统消息以及用户消息这些热数据都可以用Redis来做

  • 2.限制某段时间内的访问次数,就比如我们登录的功能可以用手机获取验证码登录,但是我们发送验证码使用的第三方,是多少钱多少条的,肯定不能让他一直点,一直发短信,就算前端js做了校验,若有些人绕过前台就麻烦了,这时候可以用redis的incr命令和expire结合起来做一个解决方案

  • 3.用于限流:计数器

  • 举个栗子:

我们在双十一经常会有一些秒杀场景,比如我们现在需要秒杀一百台0.01元的手机,库存设置100。可想而知,会有很多十万甚至百万级别的用户都在等待到点抢手机,在使用redis之前,我们的流程是这样的,即所有的并发压力都压在服务(如果你服务不拦截,就压在数据库上),很可能高并发会彻底搞垮的服务或数据库:

使用redis之后:

2、Redis 哈希(Hash)

  • 典型应用场景:

  • 记录帖子的标题、摘要、作者和封面信息,用于列表页展示

  • 记录帖子的点赞数、评论数和点击数

  • 保存一个商品信息,该信息同时带有多个商品属性,就可以考虑使用hash的数据格式进行存储。但这种场景也可以考虑使用StringKey+jsonValue的情况来实现。两种方案中,如果商品信息可能会频繁变更,hash类型会更占优势。

3、Redis 列表(List)

  • 典型使用场景:

  • 简单的消息队列:

不推荐,不可靠,且市面上已有很多成熟的消息队列产品。

消息队列本身需要保证消息顺序不打乱、不处理重复的消息和保证消息可靠性。

如果我们一定要使用list类型实现消息队列,我们需要:

  • 实现保证消息顺序

list类型可以支持。生产者使用LPUSH把消息写入队列,消费者使用RPOP把消息从队列中读取出来。

  • 消息可靠性保证(如果消息出栈消费者就宕机没处理上如何保证可靠)

消费者从List中获取一条消息后,List不会再有这条消息的留存了,但是如果消费者获取了消息,但是还没来得及处理消费者就宕机了,那么这条消息就丢失了。为了解决留存问题。List类型提供了BRPOPLPUSH命令,这个命令的作用是让消费者程序从一个List中读取消息,同时,Redis会自动把这个消息再插入到另一个List(可以叫作备份List)留存,这样就可以保证消息可靠。

  • 消息不重复处理保证(一个消息不处理两次)

list类型本身不能实现这个效果,我们需要在list的设计中加入唯一id自行保证。

  • 分页展示

  • 获取最新的列表(最新评论等等)

4、Zset有序集合

  • 典型场景

  • 排行版(例如热度榜、分类热榜)

虽然有序集合的成员是唯一的,但是分数(score)却可以重复。就比如在一个班中,学生的学号是唯一的,但是每科成绩却是可以一样的,redis可以利用有序集合存储学生成绩快速做成绩排名功能。

  • 根据点赞数展示...

例如记录帖子的点赞用户 ID 列表,评论 ID 列表,用于显示(zset同时带有排序加去重)

5、Set(集合)

  • 典型应用场景

  • 好友/关注/粉丝/感兴趣的人集合

  • 随机展示

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

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

相关文章

在职阿里6年,一个29岁女软件测试工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;14届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09;其中成功的有4家&…

新版bing(集成ChatGPT)的申请方法

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

redis知识汇总(部署、高可用、集群)

文章目录一、redis知识汇总什么是redisredis的优缺点&#xff1a;为什么要用redis做缓存redis为什么这么快什么是持久化redis持久化机制是什么&#xff1f;各自优缺点&#xff1f;AOF和RDB怎么选择redis持久化数据和缓存怎么做扩容什么是事务redis事务的概念ACID概念主从复制re…

03 OpenCV图像运算

文章目录1 普通加法1 加号相加2 add函数2 加权相加3 按位运算1 按位与运算2 按位或运算、非运算4 掩膜1 普通加法 1 加号相加 在 OpenCV 中&#xff0c;图像加法可以使用加号运算符&#xff08;&#xff09;来实现。例如&#xff0c;如果要将两幅图像相加&#xff0c;可以使用…

JVM - 类加载,连接和初始化

目录 类加载和类加载器 概述 类加载要完成的功能 加载类的方式 类加载器 类加载器的关系 类加载器说明 双亲委派模型 工作过程如下&#xff1a; 双亲委派模型说明&#xff1a; 破坏双亲委派模型&#xff1a; 类连接和初始化 类连接主要验证的内容 类连接中的解析…

c++重中之重:“换个龟壳继续套娃“:运算符重载等的学习

文章目录 前言一.运算符重载二.const成员三.取地址重载总结前言 上一期我们讲到类的6个默认构造函数中的拷贝构造函数&#xff0c;这一期我们继续往下讲&#xff0c;当然难点肯定是运算符重载了。 一、运算符重载 运算符重载是c为了增强代码的可读性引入了运算符重载&#xf…

笑死,面试官又问我SpringBoot自动配置原理

面试官&#xff1a;好久没见&#xff0c;甚是想念。今天来聊聊SpringBoot的自动配置吧&#xff1f; 候选者&#xff1a;嗯&#xff0c;SpringBoot的自动配置我觉得是SpringBoot很重要的“特性”了。众所周知&#xff0c;SpringBoot有着“约定大于配置”的理念&#xff0c;这一…

亿级高并发电商项目-- 实战篇 --万达商城项目 四(Dashboard服务、设置统一返回格式与异常处理、Postman测试接口 )

专栏&#xff1a;高并发---前后端分布式项目 &#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、…

Spring-事务2

文章目录前言一、事务的特性&#xff08;ACID&#xff09;二、事务的隔离级别三、spring中的事务平台事务管理器.事务定义ISOLation_XXX&#xff1a;**事务隔离级别.**PROPAGATION_XXX&#xff1a;**事务的传播行为**.事务状态关系&#xff1a;四、使用XML文件配置事务1、 搭建…

2023前端面试题——JS篇

1.判断 js 类型的方式 1. typeof 可以判断出’string’,‘number’,‘boolean’,‘undefined’,‘symbol’ 但判断 typeof(null) 时值为 ‘object’; 判断数组和对象时值均为 ‘object’ 2. instanceof 原理是 构造函数的 prototype 属性是否出现在对象的原型链中的任何位置 …

Vue原理解析

文章目录1. VUE的响应式原理1.1 ViewModel1.2 双向绑定的基本原理1.3 什么是响应性1.4 Vue 中的响应性是如何工作的2. Vue 渲染机制2.1 虚拟 DOM2.2 渲染管线2.3 带编译时信息的虚拟 DOM2.3.1 静态提升2.3.2 修补标记 Flags2.3.3 树结构打平2.3.4 对 SSR 激活的影响1. VUE的响应…

Zookeeper安装和基本使用

目录标题一、下载二、安装三、启动客户端测试四、使用zk一、下载 注意&#xff1a;自zk3.5.5版本以后&#xff0c;已编译的jar包&#xff0c;尾部有bin&#xff0c;应该使用的是apache-zookeeper-3.8.0-bin.tar.gz。&#xff0c;因此在下载高版本时&#xff0c;因该下载后缀带b…

华为手表开发:WATCH 3 Pro(5)点击按钮弹窗

华为手表开发&#xff1a;WATCH 3 Pro&#xff08;5&#xff09;点击按钮弹窗初环境与设备创建项目认识目录结构修改首页 -> 新建按钮 “ 按钮 ”文件名&#xff1a;**index.hml**引用包&#xff1a;system.prompt点击结果初 鸿蒙可穿戴开发 希望能写一些简单的教程和案例…

三大指标继续狂飙!重庆啤酒:不惧强弱分化加剧,深耕高端市场

十多年前&#xff0c;重庆啤酒因为9个跌停而被一片唱衰&#xff0c;资本市场经典的“关灯吃面”典故自此出现&#xff0c;被股民沿用至今。不过自2020年&#xff0c;重庆啤酒开始逆转走势&#xff0c;股价连续上涨。2021年重庆啤酒营收突破百亿大关&#xff0c;净赚11.66亿元&a…

关于小程序,你想知道的这些

近年来&#xff0c;各大平台纷纷上架小程序&#xff0c;迎来了小程序的爆发式增长。今天就来跟大家简单分享一下小程序基本的运行机制和安全机制。 小程序的由来 在小程序没有出来之前&#xff0c;最初微信WebView逐渐成为移动web重要入口&#xff0c;微信发布了一整套网页开…

自监督表征学习方法——BYOL(Bootstrap Your Own Latent)

自监督表征学习方法——BYOL(Bootstrap Your Own Latent) 参考文献&#xff1a;《Bootstrap Your Own Latent A New Approach to Self-Supervised Learning》 1.前言背景 学习良好的图像表示是计算机视觉中的一个关键挑战&#xff0c;因为它允许对下游任务进行有效的训练。许…

POE接口电路设计

首先看到PSE端&#xff0c;主要包含PSE芯片&#xff0c;MOS管&#xff08;有些PSE芯片MOS管是集成在芯片里面的&#xff09;&#xff0c;自恢复保险丝&#xff0c;还有TVS管&#xff0c;一般这个TVS管保护电压是58V的。这个电阻是用来检测POE传输的电流的&#xff0c;一般是0.几…

vue2 diff算法及虚拟DOM

概括&#xff1a;diff算法&#xff0c;虚拟DOM中采用的算法&#xff0c;把树形结构按照层级分解&#xff0c;只比较同级元素&#xff0c;不同层级的节点只有创建和删除操作。 一、虚拟DOM (1) 什么是虚拟DOM&#xff1f; 虚拟 DOM (Virtual DOM&#xff0c;简称 VDOM) 是一种…

KDDAC-10kV 电缆交流耐压及振荡波局放测试系统

一、概述 目前对电力电缆检修的管理&#xff0c;主要是依据《电力设备交接和预防性试验规程》所规定的项目和试验周期&#xff0c;定期在停电状态下进行绝缘性能试验。其中变频串联谐振试验由于试验状况接近电缆的运行工况&#xff0c;因此成为国内目前应用广泛的试验方法。 …

社科院与杜兰大学中外合作办学金融管理硕士——30+的年龄在职读研有必要吗?

说起读研&#xff0c;年龄在什么区间最合适呢&#xff1f;上次有位咨询的同学反馈年龄已经快35岁了&#xff0c;有一份不错的工作&#xff0c;但又不甘心止步于此&#xff0c;想要通过提升学历升职加薪&#xff0c;但又纠结自己是否能静下心来学习、是否能顺利毕业、拿到的证书…