在现代软件开发中,Redis因其卓越的性能和丰富的数据结构支持,被广泛用作数据库和缓存系统。本文将详细探讨如何在Windows环境下安装和使用Redis,并通过Java代码演示如何操作Redis数据库。
Redis在Windows上的图形化界面的安装与使用
1. 安装Redis图形化界面
在Linux系统中安装Redis
在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,可以显著提高应用的响应速度和扩展

4603

被折叠的 条评论
为什么被折叠?



