java redis实现Map对象类型数据缓存

Java redis存Map对象类型数据
“redis中所有的数据都是以byte[]形式存储的,所以说redis内部其实是没有数据类型的概念的.
描述
最近小编在做的就是把TR系统所有对接APP接口的返回信息进行拦截做国际化处理,要做的就是把后台系统提示的错误信息返回给移动设备端,需求就是根据app设备注册时选的语言种类(简体,繁体,英文)返回对应语种的错误提示信息,提示信息从文案系统获取过来的,可以根据错误码(errorCode)和语种language获取对应的文案提示。
考虑到这个场景会反复的查询文案系统,影响系统处理耗时和服务性能,所以为了方便及时查询检索。根据文案系统返回的数据格式,采取将文案数据型存入redis缓存,在此记录一下。
文案系统数据格式:
{
“Data”: {
“simplfiedCnDesc”: “失败”,
“traditionalCnDesc”: “失敗”,
“enDesc”: “Invalid Pass Phrase”,
“code”: “SMETR_SY_1010”
}
}

redis工具类实现具体就不展示了
直接上代码
方法:
<1>将首先我们将整个对象转成byte[]
java redis实现Map对象类型数据缓存_第1张图片代码中有传入3个参数,分别是redis存入是的key(键值), seconds(有效时间:秒), obj(缓存的对象)
由于是对byte对象处理,这里是用到了序列化,保证数据的安全。
byte[] byteData = serialize(obj);
具体代码如下:
java redis实现Map对象类型数据缓存_第2张图片这里就不用多说了,就是一个IO流的操作,记得用完要关闭哦。
redis写入缓存就已经写完了。
下面是测试类。
java redis实现Map对象类型数据缓存_第3张图片<2>读取缓存
话不多说直接上代码
java redis实现Map对象类型数据缓存_第4张图片根据redis提供的get方法取出数据,这是是测试方法
java redis实现Map对象类型数据缓存_第5张图片拿到res对象进行反序列化,
反序列化代码
java redis实现Map对象类型数据缓存_第6张图片还是和上面一样用完后记得做关闭操作。

上代码:仅供参考

 /**
     * 字节存储
     **/
    public static void setByte(String key, int seconds, Object obj) {
        try {
            byte[] byteData = serialize(obj);
            byte[] keys = key.getBytes();
            cluster.set(keys, byteData);//
            cluster.expire(keys, seconds);//有效存活时间,单位秒
        } catch (Exception e) {
            LOGGER.error("异常========key: " + key + " redis.set Exception:", e);
            Profiler.registerInfoEnd(Profiler.registerInfo(Profiler.getUmpKey() + ".redis.failed", false, true));
            throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
        }
    }

    //对象序列化
    private static byte[] serialize(Object obj) {
        ObjectOutputStream objectOutputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(obj);
            byte[] byt = byteArrayOutputStream.toByteArray();
            return byt;
        } catch (Exception e) {
            LOGGER.error("序列化异常", e);
            throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
        } finally {
            try {
                objectOutputStream.close();
                byteArrayOutputStream.close();
            } catch (IOException io) {
                throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
            }
        }
    }

    // 对象反序列化
    public static Object unserizlize(byte[] byt) {
        ObjectInputStream oii = null;
        ByteArrayInputStream bis = null;
        bis = new ByteArrayInputStream(byt);
        try {
            oii = new ObjectInputStream(bis);
            Object obj = oii.readObject();
            return obj;
        } catch (Exception e) {
            LOGGER.error("反序列化异常", e);
            throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
        } finally {
            try {
                oii.close();
                bis.close();
            } catch (IOException io) {
                throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
            }
        }
    }

    public static byte[] getByte(String key) {
        byte[] val;
        try {
            val = cluster.get(key.getBytes());
        } catch (Exception e) {
            LOGGER.error("key:" + key + " redis.get Exception:", e);
            Profiler.registerInfoEnd(Profiler.registerInfo(Profiler.getUmpKey() + ".redis.failed", false, true));
            throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
        }
        return val;
    }

    public static void delByte(String key) {
        try {
            cluster.del(key.getBytes());
        } catch (Exception e) {
            LOGGER.error("key:" + key + " redis.del Exception:", e);
            Profiler.registerInfoEnd(Profiler.registerInfo(Profiler.getUmpKey() + ".redis.failed", false, true));
            throw new PersistentException(JSFCodeEnum.SMETR_CA_1009);
        }
    }

这是测试代码

    @ResponseBody
    @RequestMapping("/clear")
    public Object clear(@RequestBody RpcRequest<LoanConfirmPageInfoReq> request){
        //清空缓存中的文案信息后门
        RedisUtils.delByte(ChainConts.WA_KEY);
        return  "清除文案缓存成功";
    }

    @ResponseBody
    @RequestMapping("/setRedis")
    public Object testRedis(@RequestBody RpcRequest<LoanConfirmPageInfoReq> request) {
        //文案信息
        UedimMessagesInter uedimMessagesInter = new UedimMessagesInter();
        uedimMessagesInter.setCode("SMETR_SY_1010");
        uedimMessagesInter.setEnDesc("Invalid Pass Phrase");
        uedimMessagesInter.setSimplfiedCnDesc("Pass Phrase验证失败");
        uedimMessagesInter.setTraditionalCnDesc("Pass Phrase驗證失敗");

        Map<String, UedimMessagesInter> map =new HashMap<String,UedimMessagesInter>();
        map.put("tr",uedimMessagesInter);
        //設置緩存過期
        RedisUtils.setByte(ChainConts.WA_KEY,60*2,map);
        return "有效時間2分鐘,插入緩存Key: "+ChainConts.WA_KEY+",內容value:"+map;
    }

    @ResponseBody
    @RequestMapping("/getRedis")
    public Object getRedis(@RequestBody RpcRequest<LoanConfirmPageInfoReq> request) {
        byte[] res = RedisUtils.getByte(ChainConts.WA_KEY);
        if(res!=null){
            //反序列化
            Map<String, UedimMessagesInter> map = ( Map<String, UedimMessagesInter> )RedisUtils.unserizlize(res);
            return "緩存Key: "+ChainConts.WA_KEY+",value :"+map.toString();
        }else {
            return "緩存取值為空"+res;
        }
    }

最后总结下,当你有一个大对象需要存在redis里面的时候,不知道要存什么,那么久选择byte吧,这存储要优于String

10w数据 时间 内存占用
存json 10s 14M
存byte 6s 6M
存jsonMap 10s 20M
存byteMap 4s 4M
取json 7s
取byte 4s
取jsonmap 7s
取bytemap 4s
最后的结果就是:10w数据的时候,submit转json的过程要比submit转byte数组慢了2-3s,存redis的时候又慢了2s;100w数据的时候,存string的方式直接3个线程挂了,存byte也挂了1个线程。综上来说,存byte的方式要优于存string。
参考: redis的两种存储方式string和byte对比

你可能感兴趣的:(java redis实现Map对象类型数据缓存)