Redis】Redis如何存储和操作Java对象

2021-03-26 10:04发布

12条回答
我是大脸猫
2楼 · 2021-03-26 14:17

根据redis的存储原理,Redis的key和value都支持二进制安全的字符串


1.利用序列化和反序列化的方式

存储java对象我们可以通过对象的序列化与反序列化完成存储于取出,这样就可以使用redis存储java对象了


步骤:创建一个序列化和反序列化的工具类


public class SerializeUtil {  

public static byte[] serialize(Object object) {  

ObjectOutputStream oos = null;  

ByteArrayOutputStream baos = null;  

try {  

//序列化  

baos = new ByteArrayOutputStream();  

oos = new ObjectOutputStream(baos);  

oos.writeObject(object);  

byte[] bytes = baos.toByteArray();  

return bytes;  

} catch (Exception e) {  

}  

return null;  

}  

public static Object unserialize(byte[] bytes) {  

ByteArrayInputStream bais = null;  

try {  

//反序列化  

bais = new ByteArrayInputStream(bytes);  

ObjectInputStream ois = new ObjectInputStream(bais);  

return ois.readObject();  

} catch (Exception e) {  

}  

return null;  

}  

}


每次存储和取出对象时都是需要调用方法序列与反序列的


方法2:将java对象转换为json字符串,利用json与java对象之间可以相互转换的方式进行存值和取值

具体存值和取值在上一篇文章中有写json与java对象的相互转换问题



我想吃肉
3楼 · 2021-03-26 14:43

下面是一个如何使用Redisson创建Java活动对象的示例。使用活动对象需要@REntity和@RId批注。

Java

1

@REntity

2

public class MyObject {

3

4

@RId

5

private String id;

6

7

@RIndex

8

private String field1;

9

10

@RIndex

11

private Integer field2;

12

13

@RIndex

14

private Long field3;

15

16

}

创建RLO并将其存储在Redis中后,您也可以使用Redisson进行搜索。可用的搜索条件包括:

· Condition.eq:将属性限制为定义值的“ EQUALS”条件。

· Condition.and: “ AND”条件,用于嵌套条件的集合。

· Condition.or:嵌套条件集合的“ OR”条件。

· Condition.in将属性限制为一组定义值的“ IN”条件。

· Condition.gt: “大于”条件将属性限制为定义的值。

· Conditions.ge: “大于等于”条件,用于将属性限制为定义的值。

· Conditions.lt: “小于”条件,用于将属性限制为定义的值。

· Conditions.le: “小于或等于”条件将属性限制为定义的值。

以下是如何在Redisson中搜索Java活动对象的示例。此示例搜索将找到所有对象,其中field1 =值且field2 <12 field1 =值且field2> 23,或field3在[1,2]范围内。

Java

1

RLiveObjectService liveObjectService = redisson.getLiveObjectService();

2

liveObjectService.persist(new MyObject());

3

4

Collection objects = liveObjectService.find(MyObject.class,

5

Conditions.or(Conditions.and(Conditions.eq("field1", "value"), Conditions.lt("field2", 12)),

6

Conditions.and(Conditions.eq("field1", "value2"), Conditions.gt("field2", 23)),

7

Conditions.in("field3", 1L, 2L));

8

Redisson PRO为Java对象实现了Redis搜索引擎,该引擎比开源版本快10倍,同时还降低了JVM内存消耗。


想用Redis存储java对象,首先需要把java对象序列化成byte数组,然后再进行存储。取出数据后,再反序列化成java对象即可。由此我们知道,每次存储和读取都需要进行序列化和反序列化。可以选择java自带的序列化功能(速度较慢,被序列化的类必须实现Serializable接口),也可以选择一些第三方写的牛逼的序列化工具,这里介绍使用kryo。引入pom依赖:


com.esotericsoftware

kryo

4.0.0

 

redis.clients

jedis

2.9.0

编写一个基本的序列化和反序列化类,


KryoSerializeUtil.java


import java.io.ByteArrayOutputStream;

import java.io.IOException;

 

import com.esotericsoftware.kryo.Kryo;

import com.esotericsoftware.kryo.io.Input;

import com.esotericsoftware.kryo.io.Output;

 

/**

 * 使用Kryo

 * 把java对象序列化和反序列化

 * 虽然所序列化和反序列化的类无需实现java.io.Serializable接口,

 * 但还是建议实现java.io.Serializable接口,避免类修改后无法反序列化

 * @author LAN

 * @date 2018年11月13日

 */

public class KryoSerializeUtil {

/**

* 把java对象序列化成byte数组

* @author LAN

* @date 2018年11月13日

* @param object

* @return

*/

public static byte[] serialize(Object object) {

if(object==null) {

return null;

}

ByteArrayOutputStream baos = null;

Output output = null;

try {

Kryo kryo = new Kryo();

baos = new ByteArrayOutputStream();

output = new Output(baos);

kryo.writeObject(output, object);

output.flush();

return baos.toByteArray();

}  finally {

try {

if(baos!=null) baos.close();

} catch (IOException e) {

e.printStackTrace();

}

output.close();

}

}

/**

* 把byte数组反序列化得到java对象

* @author LAN

* @date 2018年11月13日

* @param bytes

* @param clazz

* @return

*/

public static T unserialize(byte[] bytes, Class clazz) {

if(bytes==null || bytes.length==0) {

return null;

}

Kryo kryo = new Kryo();

Input input = new Input(bytes);

T obj = kryo.readObject(input, clazz);

input.close();

return obj;

}

}

编写一个RedisUtil实现储存和读取java对象


RedisUtil.java


import java.util.ArrayList;

import java.util.List;

import java.util.Set;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

import redis.clients.jedis.JedisPoolConfig;

 

public class RedisUtil {

private static String redisUrl = "127.0.0.1";

private static int redisPort = 6379;

private static String redisPassword = null;

private static int database = 1;// 可选0-15

 

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

 

private static volatile JedisPool jedisPool = null;

 

private RedisUtil() {

}

/**

* 服务器整个应用关闭后(不是单个方法结束后),可考虑调用此方法销毁连接池

* @author LAN

* @date 2018年11月14日

*/

public static void destroy() {

if(jedisPool==null) return;

if(!jedisPool.isClosed()) jedisPool.close();

jedisPool.destroy();

}

 

private static Jedis getConnection() {

if (jedisPool == null) {

synchronized (RedisUtil.class) {// 线程安全

if (jedisPool == null) {

logger.debug("=================创建jedisPool Start=================");

JedisPoolConfig config = new JedisPoolConfig();

config.setMaxTotal(200);//最大连接数, 默认8个

config.setMaxIdle(8);//最大空闲连接数, 默认8个

config.setMaxWaitMillis(1000 * 100);//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1

config.setTestOnBorrow(true);

jedisPool = new JedisPool(config, redisUrl, redisPort, 100000, redisPassword, database);

logger.debug("=================创建jedisPool End=================");

}

}

}

return jedisPool.getResource();

}

 

/**

* @author LAN

* @date 2018年11月14日

* @param key     存储的键

* @param o       存储的java对象

* @param expire  设置过期时间,单位:秒,小于0时为永不过期

*/

public static void set(String key, Object o, int expire) {

Jedis jedis = null;

try {

jedis = getConnection();

if(o==null) {

jedis.del(key.getBytes());

return;

}

byte[] data = KryoSerializeUtil.serialize(o);

if(expire>0) {

jedis.setex(key.getBytes(), expire, data);

}else {

jedis.set(key.getBytes(), data);

}

}finally {

if(jedis!=null) jedis.close();//新版本的close方法,如果是从JedisPool中取出的,则会放回到连接池中,并不会销毁。

}

}

public static void set(String key, Object o) {

set(key, o, -1);

}

public static T get(String key, Class clazz) {

Jedis jedis = null;

try {

jedis = getConnection();

byte[] data = jedis.get(key.getBytes());

if(data==null || data.length==0){

return null;

}

T t = (T) KryoSerializeUtil.unserialize(data, clazz);

return t;

}finally {

if(jedis!=null) jedis.close();//新版本的close方法,如果是从JedisPool中取出的,则会放回到连接池中,并不会销毁。

}

}

}

通过set方法,可把java对象保存到Redis中,当然也可保存List对象等,并且可以设置过期时间(针对缓存特别有用);通过get方法,可以直接拿到存进去的java对象。注意,上述代码中如果使用jedis版本较低时,每个finally块中释放jedis连接的方法是不一样的,旧版本可能要用jedisPool.returnResource释放连接回到连接池中。


写一个main方法测试:


TestRedis.java


package com.lan.LanUtil;

 

import java.util.ArrayList;

import java.util.List;

import com.lan.LanUtil.utils.RedisUtil;

 

public class TestRedis {

 

public static void main(String[] args) {

StringBuilder sb1 = new StringBuilder("天天学习,好好进步!");

RedisUtil.set("sb", sb1);

List list = new ArrayList<>();

sb1 = new StringBuilder("进步!进步!进步!");

list.add(sb1);

list.add(new StringBuilder("好好学习,天天向上!"));

RedisUtil.set("list", list);

StringBuilder sb2 = RedisUtil.get("sb", StringBuilder.class);

List list2 = RedisUtil.get("list", ArrayList.class);

System.out.println(sb2);

for(StringBuilder s:list2) {

System.out.println(s);

}

}

}

运行结果:




其实对复杂的java类及List等都是可以进行存取的,事实上能存取什么java数据类型完全与序列化工具有关,和redis是无关的。


Redis 支持五种数据类型:String(字符串)、Hash(哈希)、List(列表),set(集合)、zset( sorted set:有序集合)

嘿呦嘿呦拔萝卜
6楼 · 2021-03-26 17:18

根据redis的存储原理,Redis的key和value都支持二进制安全的字符串

1.利用序列化和反序列化的方式

存储java对象我们可以通过对象的序列化与反序列化完成存储于取出,这样就可以使用redis存储java对象了

步骤:创建一个序列化和反序列化的工具类


aijingda
7楼 · 2021-03-26 17:21

想用Redis存储java对象,首先需要把java对象序列化成byte数组,然后再进行存储。取出数据后,再反序列化成java对象即可。由此我们知道,每次存储和读取都需要进行序列化和反序列化。可以选择java自带的序列化功能(速度较慢,被序列化的类必须实现Serializable接口),也可以选择一些第三方写的牛逼的序列化工具,这里介绍使用kryo。引入pom依赖,代码如下:



 com.esotericsoftware
 kryo
 4.0.0

 

 redis.clients
 jedis
 2.9.0


清屿
8楼 · 2021-03-27 16:39

Redis 支持五种数据类型:String(字符串)、Hash(哈希)、List(列表),set(集合)、zset( sorted set:有序集合)

是你的小甜心呀
9楼 · 2021-03-27 18:52

下面是一个如何使用Redisson创建Java活动对象的示例。使用活动对象需要@REntity和@RId批注。

Java

1

@REntity

2

public class MyObject {

3

4

@RId

5

private String id;

6

7

@RIndex

8

private String field1;

9

10

@RIndex

11

private Integer field2;

12

13

@RIndex

14

private Long field3;

15

16

}

创建RLO并将其存储在Redis中后,您也可以使用Redisson进行搜索。可用的搜索条件包括:

· Condition.eq:将属性限制为定义值的“ EQUALS”条件。

· Condition.and: “ AND”条件,用于嵌套条件的集合。

· Condition.or:嵌套条件集合的“ OR”条件。

· Condition.in将属性限制为一组定义值的“ IN”条件。

· Condition.gt: “大于”条件将属性限制为定义的值。

· Conditions.ge: “大于等于”条件,用于将属性限制为定义的值。

· Conditions.lt: “小于”条件,用于将属性限制为定义的值。

· Conditions.le: “小于或等于”条件将属性限制为定义的值。

以下是如何在Redisson中搜索Java活动对象的示例。此示例搜索将找到所有对象,其中field1 =值且field2 <12 field1 =值且field2> 23,或field3在[1,2]范围内。

Java

1

RLiveObjectService liveObjectService = redisson.getLiveObjectService();

2

liveObjectService.persist(new MyObject());

3

4

Collection

5

Conditions.or(Conditions.and(Conditions.eq("field1", "value"), Conditions.lt("field2", 12)),

6

Conditions.and(Conditions.eq("field1", "value2"), Conditions.gt("field2", 23)),

7

Conditions.in("field3", 1L, 2L));

8

Redisson PRO为Java对象实现了Redis搜索引擎,该引擎比开源版本快10倍,同时还降低了JVM内存消耗。



相关问题推荐

  • 回答 1

    redis,你要搞高并发的话,不可避免,要把底层的缓存搞得很好mysql,高并发,做到了,那么也是通过一系列复杂的分库分表,订单系统,事务要求的,QPS到几万,比较高了要做一些电商的商品详情页,真正的超高并发,QPS上十万,甚至是百万,一秒钟百万的请求量光...

  • 虚拟机安装RedisLinux Redis 2021-01-18 09:45
    回答 1

    1。重现安装liunx系统,最好下其他版本的镜像,再下载redis2。可以去网上下载其他人的已经安装好redis的镜像,直接可以用

  • 回答 2

    1、在线安装方式,找到安装的地址,删除安装目录,重新拉取rpm包,测试是否是环境问题,如果环境本身没有问题再查看自己的安装步骤,逐个命令的排查,锁定问题;2、离线安装方式,找到自己的安装包,确定安装包本身没有问题,那么查看tar解压后的安装目录结构...

  • 回答 2

    RDB定时快照方式(snapshot): RDB 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。AOF基于语句追加文件的方式:则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。一般来说, 如果想...

  • 回答 1

    区别:RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。 AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不...

没有解决我的问题,去提问