Redis实战--Windows上的Redis使用及Java代码操作Redis

        在现代软件开发中,Redis因其卓越的性能和丰富的数据结构支持,被广泛用作数据库和缓存系统。本文将详细探讨如何在Windows环境下安装和使用Redis,并通过Java代码演示如何操作Redis数据库。

Redis简单介绍与安装应用-CSDN博客

Redis在Windows上的图形化界面的安装与使用

1. 安装Redis图形化界面

Linux系统安装Redis

Redis简单介绍与安装应用-CSDN博客

Windows系统进行远程连接

通过网盘分享的文件:Another-Redis-Desktop-Manager 提取码: 96jg

 

2. 图形化界面操作

Windows系统上安装与使用Redis数据库

1. 安装Redis

通过网盘分享的文件:redisbin_x64 提取码: jjjp

直接解压缩

 2.远程连接Redis

3. 使用Redis

基本命令

keys *

查看当前库的所有键

exists <key>

判断某个键是否存在

type <key>

查看键的类型

del <key>

删除某个键

expire <key><seconds>

为键值设置过期时间,单位秒

ttl <key>

查看还有多久过期,-1表示永不过期,-2表示已过期

dbsize

查看当前数据库中key的数量

flushdb

清空当前库

flushall

通杀全部库

Redis 数据类型

1)String —— 字符串类型

字符串类型的value值,可以占用512M的空间,所以可以存储很多的数据。

get <key>

查询对应键值

set <key><value>

添加键值对

append <key><value>

将给定的<value>追加到原值的末尾

strlen <key>

获取值的长度

setnx <key><value>

只有在key 不存在时设置key的值,SET if Not eXists

incr <key>

将key中存储的数字值增1只能对数字值操作,如果为空,新增值为1

decr <key>

将key中存储的数字值减1只能对数字之操作,如果为空,新增值为-1

incrby /decrby <key> 步长

将key中存储的数字值增减,自定义步长

mset <key1><value1><key2><value2>

同时设置一个或多个key-value对

mget <key1><key2><key3>

同时获取一个或多个value

msetnx <key1><value1><key2><value2>

同时设置一个或多个key-value对,当且仅当所有给定的key都不存在

getrange <key> <起始位置> <结束位置>

获得值的范围,类似java中的substring

setrange <key> <起始位置> <value>

用<value>覆盖<key>所存储的字符串值,从<起始位置>开始

setex <key> <过期时间> <value>

设置键值的同时,设置过去时间,单位秒

getset <key><value>

以新换旧,设置了新值的同时获取旧值

2) List —— 散列类型

有序的(插入的时候有序),底层是一个双向链表

3) Set —— 列表类型

Set的特点是无序不重复的

sadd <key><value1><value2> ....

将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。

smembers <key>

取出该集合的所有值。

sismember <key><value>

判断集合<key>是否为含有该<value>值,有返回1,没有返回0

scard <key>

返回该集合的元素个数。

srem <key><value1><value2> ....

删除集合中的某个元素。

spop <key>

随机从该集合中吐出一个值。

srandmember <key><n>

随机从该集合中取出n个值。不会从集合中删除

sinter <key1><key2>

返回两个集合的交集元素。

sunion <key1><key2>

返回两个集合的并集元素。

sdiff <key1><key2>

返回两个集合的差集元素。

4) Hash —— 集合类型

Redis hash 是一个键值对集合

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

hset <key><field><value>

<key>集合中的 <field>键赋值<value>

hget <key1><field>

从<key1>集合<field> 取出 value

hmset <key1><field1><value1><field2><value2>...

批量设置hash的值

hexists key <field>

查看哈希表 key 中,给定域 field 是否存在。

hkeys <key>

列出该hash集合的所有field

hvals <key>

列出该hash集合的所有value

hincrby <key><field><increment>

为哈希表 key 中的域 field 的值加上增量 increment

hsetnx <key><field><value>

将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

5) Zset(Sorted Set)—— 有序集合类型

zrange <key><start><stop> [WITHSCORES]

返回有序集 key 中,下标在<start><stop>之间的元素带WITHSCORES,可以让分数一起和值返回到结果集。

zrangebyscore key min max withscores

返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。

zrevrangebyscore key max min withscores

同上,改为从大到小排列。

zincrby <key><increment><value>

为元素的score加上增量

zrem <key><value>

删除该集合下,指定值的元素

zadd <key><score1><value1><score2><value2>...

将一个或多个 member 元素及其 score 值加入到有序集 key 当中

zcount <key><min><max>

统计该集合,分数区间内的元素个数

zrank <key><value>

返回该值在集合中的排名,从0开始。

Java代码操作Redis

1. 创建Java项目

        在Java项目中操作Redis,首先需要引入Jedis库。可以通过Maven或Gradle将Jedis依赖添加到项目中。

2. 使用Jedis操作Redis

Jedis是Redis的Java客户端,提供了丰富的API来操作Redis。

导入包

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>

创建项目

单一连接模式

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.*;


/**
 * @Before @After 修饰的方法,是在运行每一个@Test 之前或者之后运行的
 */
public class JedisTest {

    Jedis jedis = null;
    @Before
    public void initDB(){
        // 连接redis数据库
        jedis = new Jedis("localhost",6379);
        // 假如设置了密码,需要使用auth
        //jedis.auth("密码");
        // 通过ping 可以返回一个 pong 说明连接正常
        //System.out.println(jedis.ping());
    }

    @After
    public void destroyDB(){
        // 数据库关闭
        jedis.close();
    }

    @Test
    public void testString(){
        // 数据库操作
        jedis.set("age","20");
        System.out.println(jedis.get("age"));
    }

    @Test
    public void testKeys(){
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);
    }

    @Test
    public void testSet(){
        // String... abc 说明这个参数是一个可变长的参数,参数的数量不限,一般必须写在最后一个参数的位置
        // 想set中设置值
        jedis.sadd("set01","a","b","b","c");
        Set<String> set01 = jedis.smembers("set01");
        System.out.println(set01);

    }

    @Test
    public void testHash(){

        jedis.hset("class","1001","帅岩");
        jedis.hset("class","1002","正阳");
        jedis.hset("class","1003","自力");

        System.out.println(jedis.hkeys("class"));
        System.out.println(jedis.hvals("class"));
        Map<String, String> map = jedis.hgetAll("class");
        // map 中如何循环遍历?
        // 第一种办法
        Set<String> keys = map.keySet();
        for (String key:keys) {
            System.out.println(key+","+map.get(key));
        }
        // 第二种办法
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String,String> entry:entries) {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }

    }


    // 复习一下可变长的方法
    public void abc(String a,String b,String... c){
        System.out.println(a);
        System.out.println(b);
        System.out.println(c.length);
        // [Ljava.lang.String;@e2d56bf 本质是一个数组(引用数据类型)
        System.out.println(c);
        System.out.println(Arrays.toString(c));
    }

    @Test
    public void  testList(){
        jedis.lpush("list02","a","b","b","c");
        List<String> list01 = jedis.lrange("list02", 0, -1);
        System.out.println(list01);
        abc("name","age","zhangsan","lisi","wangwu");
    }

    @Test
    public void testZSet(){
        HashMap<String, Double> map = new HashMap<>();
        map.put("aaa",1d);
        map.put("bbb",3d);
        map.put("ccc",4d);
        map.put("ddd",2d);
        jedis.zadd("zset01",map);

        // 获取所有元素
        System.out.println(jedis.zcard("zset01"));
        System.out.println(jedis.zrange("zset01", 0, -1));
        System.out.println(jedis.zrevrange("zset01", 0, -1));
        System.out.println(jedis.zrangeWithScores("zset01", 0, -1));
    }

}
package com.bigdata;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;

import java.util.*;

public class TestRedis {

    Jedis jedis = null;
    @Before
    public void init(){
        jedis = new Jedis("localhost",6379);
        System.out.println(jedis);
    }

    @Test
    public void testString(){
        jedis.set("name","zhangsan");
        // keys *
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);
        Long time = jedis.expire("name", 10);
        System.out.println(time);
        Long syTime = jedis.ttl("name");
        System.out.println(syTime);
    }

    @Test
    public void testList(){
        jedis.lpush("list02","a","b","c","d");
        List<String> list02 = jedis.lrange("list02", 0, -1);
        System.out.println(list02);
        System.out.println(jedis.lpop("list02"));
        System.out.println(jedis.lrem("list02", 1, "a"));
    }

    // 可变长参数的使用 ,可变长参数是基本数据类型跟上...  代表该参数可以传递无数个,必须放在一个方法的参数的最后一个
    public void setValue(String name,int age,int... scores){
        // 该参数的用法跟数组是一样的
        System.out.println(scores.length);
        // 数组是对象 -- 因为除了基本数据类型之外,都是引用数据类型
        System.out.println(scores);
        System.out.println(Arrays.toString(scores));
        // foreach 循环
        for(int score:scores){
            System.out.println(score);
        }
        // for 循环
        for(int i=0;i<scores.length;i++){
            System.out.println(scores[i]);
        }
    }

    @Test
    public void testSet(){
        //
        // setValue("laoyan",20,100,100,100);
        jedis.sadd("set02","zs","lisi","wangwu");
        Long set02 = jedis.scard("set02");
        Set<String> set021 = jedis.smembers("set02");
        System.out.println(set021);
        String set022 = jedis.srandmember("set02");
        System.out.println(set022);

    }

    @Test
    public void testHash(){
        jedis.hset("class","name","shengsai");
        jedis.hset("class","age","19");
        jedis.hset("class","gender","nan");

        String age = jedis.hget("class", "age");
        System.out.println(age);

        Map<String, String> allKeyValue = jedis.hgetAll("class");
        System.out.println(allKeyValue);

        Set<String> keysValue = jedis.hkeys("class");
        System.out.println(keysValue);



    }

    @Test
    public void testZSet(){
        HashMap<String, Double> hashMap = new HashMap<>();
        hashMap.put("张三",1d);
        hashMap.put("lisi",1.3d);
        hashMap.put("wangwu",2.1d);
        hashMap.put("赵六",1.7d);
        jedis.zadd("zset02",hashMap);
        jedis.zadd("zset02",0.99d,"laoyan");

        System.out.println(jedis.zrange("zset02", 0, -1));

        // Tuple 是元组的意思  (元祖食品、福晶园)
        Set<Tuple> zset02 = jedis.zrangeByScoreWithScores("zset02", 0, 3);
        System.out.println(zset02);

    }



    @After
    public void destory(){

        if(jedis != null){
            jedis.close();
        }

    }
}

Jedis经常性的被创建,创建一次就是一次连接,连接操作完断开,下一次再连。

连接池模式

        为了提高性能,避免频繁创建和销毁连接,可以使用Jedis连接池。将使用完之后的连接,不销毁,而是放入到连接池中,等下一个操作者过来的时候就不需要创建了,可以避免频繁的创建连接,从而提高了效率。

import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisPoolTest {

    Jedis jedis = null;
    @Before
    public void initDB(){
        // JedisPool jedisPool = new JedisPool("localhost", 6379);
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        // idle 空闲的 最大空闲
        poolConfig.setMaxIdle(200);
        // 最大的连接数量
        poolConfig.setMaxTotal(1000);
        // 最小空闲
        poolConfig.setMinIdle(5);

        JedisPool jedisPool = new JedisPool(poolConfig,"localhost");
        jedis = jedisPool.getResource();
    }

    @After
    public void destroyDB(){
        // 数据库关闭
        jedis.close();
    }

    /**
     *  常见的数据库连接池有:c3p0 dbcp druid  HikariCP等
     */
    @Test
    public void testPool(){
        System.out.println(jedis.get("age"));
    }
}

        使用java代码操作redis 我们目前使用的是 jedis ,但是不是说必须只能用jedis,而是java可以通过很多技术操作redis,比如java工程师可以使用redisTemplate的一个技术去操作。

Redis缓存应用

        Redis作为缓存数据库,可以显著提高应用性能。以电商应用中的goods_cats表为例,首次查询时将结果存入Redis,后续查询直接从Redis中获取,避免了重复查询数据库。

将所需数据导入MySQL数据库

所需数据在最上方

代码示例

以下是使用Jedis连接池从Redis中获取和设置数据的示例代码。

导入包

<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

         <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.1</version>
        </dependency>
</dependencies>

通过代码获取数据

先判断缓存中是否有这个数据
缓存没有,直接查询数据库,将数据打印出来,并且将查询查询出来的数据放入redis缓存
缓存有,从缓存中获取分类数据,直接打印。

package com.bigdata;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bigdata.utils.JdbcUtils;
import com.bigdata.utils.JedisPoolUtils;
import redis.clients.jedis.Jedis;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Main {
    public static void main(String[] args) throws Exception{

        /**
         *  思路:
         *  通过代码第一次获取
         *     分类数据,先判断缓存中是否有这个数据
         *     缓存没有,直接查询数据库,将数据打印出来,并且将查询查询出来的数据放入redis缓存
         *  假如不是第一次查询:
         *     从缓存中获取分类数据,直接打印。
         */
        // 连接redis,查询缓存判断是否有数据
        Jedis jedis = JedisPoolUtils.getJedis();
        // 第一次这个key肯定不存在
        if(!jedis.exists("shop-category")){

            // 从数据库获取分类数据  jdbc 技术
            Connection connection = JdbcUtils.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement("select catId,parentId,catName from goods_cats where isShow=1");
            ResultSet resultSet = preparedStatement.executeQuery();
            // 将结果变为 json 字符串
            String jsonResult = JdbcUtils.changeResultToJson(resultSet);

            System.out.println("第一次从数据库中获取数据");
            System.out.println(jsonResult);

            // 还需要将数据放入redis里面
            jedis.set("shop-category",jsonResult);

        }else{
            // 通过key 获取数据
            String jsonStr = jedis.get("shop-category");
            System.out.println("缓存中已经存在,从缓存拿数据");
            System.out.println(jsonStr);
            // 这个json可以变为对象 --赠送的
            JSONArray array = JSON.parseArray(jsonStr);
            for (int i = 0; i < array.size(); i++) {
                Object o = array.get(i);
                String json = o.toString();
                JSONObject jsonObject = JSON.parseObject(json);
                System.out.println(jsonObject.getString("catName"));
            }
        }

    }
}

连接数据库的工具类

package com.bigdata.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class JdbcUtils {


    public static Connection getConnection() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/shop?useSSL=false";
        String user="root";
        String password ="123456";
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }

    // 这个方法有两个作用,一个是打印结果集,一个是返回拼接的字符串
    public static String printResultSet(ResultSet resultSet) throws SQLException {

        StringBuffer sb = new StringBuffer();
        while(resultSet.next()){

            String category_code = resultSet.getString("category_code");
            String category_name = resultSet.getString("category_name");
            sb.append(category_code).append("-").append(category_name);
            System.out.println(category_code);
            System.out.println(category_name);
        }
        return sb.toString();

    }

    public static String changeResultToJson(ResultSet resultSet) throws SQLException {

        ArrayList<JSONObject> list = new ArrayList<>();

        while(resultSet.next()){
            // catId,parentId,catName
            String catId = resultSet.getString("catId");
            String parentId = resultSet.getString("parentId");
            String catName = resultSet.getString("catName");

            // 使用 fastjson
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("catId",catId);
            jsonObject.put("parentId",parentId);
            jsonObject.put("catName",catName);

            list.add(jsonObject);
        }

        return JSON.toJSONString(list);

    }
}

 结论

        Redis是一个功能强大的内存数据库,适用于缓存和消息队列等场景。在Windows上,虽然安装稍显复杂,但通过图形化工具可以简化管理过程。Java通过Jedis库提供了与Redis交互的便捷方式,无论是直接连接还是使用连接池,都能有效地操作Redis。通过将数据缓存到Redis,可以显著提高应用的响应速度和扩展

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天冬忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值