【Redis 二】Jedis操作Redis的String类型

       上一篇写了一个《Jedis操作Redis有序集合类型(SortedSet)》,对于实战来说当然是需要将Redis支持的五种类型都熟悉和了解的,接下来就是Jedis操作Redis的String类型。

          Redis支持的字符串可以是(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB !

         然后来看看什么情况下会使用呢?

  1. 其实在Redis中String 类型是使用的最广泛的,在当做缓存的时候用来给数据库缓解压力、
  2. 在很多地方redis被用来计数,因为redis 可以快速计数、查询缓存、同时数据还可以一步落地到其他数据源、
  3. redis被用来集中管理用户的session,这是出现在负载均衡的情况下,用户的信息被存储在不同的服务器上,为了不让用户刷新之后会重新登录,将用户信息更新和登录信息在redis上获取,只要Redis是高可用、数据一致的就可以保证用户信息一致,不登出了。
  4. 使用在获取短信的接口上,对短信接口设置过期时间,限制用户每分钟获取验证码的频率,这样短信接口就可以减少流量访问了
 private void setStringValue(String key){

        //新增key,成功返回 OK
        String result = getJedis().set(key, "设置一个String值");

        //根据key,获取值
        getJedis().get(key);

        //strlen 读取value长度 根据key获取到value的长度
        Long strlen = getJedis().strlen(key);

        //只有String类型的key才有的过期时间,设置过期时间为5秒
        Long expire = getJedis().expire(key, 5);

        //既然设置了过期时间,那么查看某个key的剩余生存时间,单位秒,永久生存或者不存在的都返回-1
        Long ttlTime = getJedis().ttl(key);

        //当然也可以移除某个key的生存时间
        Long persist = getJedis().persist(key);
        System.out.println("移除生存时间后 ttl of " + key + "=" + getJedis().ttl(key));
        //查看key所储存的值的类型
        String type = getJedis().type(key);


        //一次性新增多个key
        getJedis().mset("key001", "value001", "key002", "value002", "key003",
                "value003", "key004", "value004");

        //读取所有key,遍历,判断类型 字符匹配规则 可以是 XXX* 以XXX开头的key,当然可以使用正则表达式,但是不推荐
        Set keys = getJedis().keys("*");

        Iterator it = keys.iterator();
        while (it.hasNext()) {
            key = it.next();
            if (getJedis().type(key).equals("string")){
                System.out.println("读取所有key并筛选string类型 get " + key + "=" + getJedis().get(key));
            }
        }

        //一次性获取多个key值
        List list = getJedis().mget("key001", "key002", "key003", "key004");
        System.out.println("一次性获取多个key值:"+list);

        //一次性删除多个key参数为一个字符串数组,返回成功删除个数
        Long del = getJedis().del(new String[] { "key001", "key002" });

        // 禁止覆盖
        Long setnx = getJedis().setnx("key003", "value003_new");

        //新增key同时设置有效期(秒)
        result = getJedis().setex(key, 3, "setex demo");
        System.out.println("result"+result+"[4秒之前]get " + key + "=" + getJedis().get(key));
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
        }
        System.out.println("[4秒之后]get " + key + "=" + getJedis().get(key));

        //获取原值, 更新为新值一步完成
        key = "key003";
        String former = getJedis().getSet(key, "value002-after-getset");
        System.out.println("getSet 原值:" + former + "; 新值" + getJedis().get(key));

        //incr 自增
        key = "redis_num";
        getJedis().del(key);
        ////如果key存在,则value的值为:key+1   如可以不存在,则生成value为0的key,再+1
        long incr = getJedis().incr(key);
        //与上面不同的是增加值是传进来的value 多为存储的value为数字
        getJedis().incrBy(key, Integer.parseInt(value));
        Long decr = getJedis().decrBy(key, 100);

        //给某一个键 追加值
        Long appendValue = getJedis().append(key, "appendValue");

        //设置指定位置的字符 源redis 命令 setrange key offeset value 注意是字符
        Long setrange = getJedis().setrange(key, 2, "special");

        //获取部分字符串  getrange key start end
        getJedis().getrange(key,0,10);

        //Redis Incr 命令将 key 中储存的数字值增一,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作,且将key的有效时间设置为长期有效。
        //Redis Incrby 命令将 key 中储存的数字加上指定的增量值,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
        //Redis Hincrby 命令用于为哈希表中的字段值加上指定增量值
    }

其实Redis是巨大的Map是一个key-value的存储系统,其中Key类型一般都是为String,而Value的类型则为Redis 对象(redis object),所以可以绑定不同的类型,譬如 string、list 和set。

       来说说String类型,String是Redis最基本的类型,而且String类型是二进制安全的。意思是Redis的string可以包含任何数据,比如jpg图片或者序列化的对象。从内部实现来看其实string可以看作byte数组,最大上限是1G字节。 

struct sdshdr {
   //buf 中已占用空间的长度  
   long len;
   // buf 中剩余可用空间的长度 
   long free;
   //字符数组 用于记录我们的字符串(记录Redis)
   char buf[];

};

buf是个char数组用于存贮实际的字符串内容。其实char和c#中的byte是等价的,都是一个字节 ,len是buf数组的长度,free是数组中剩余可用字节数。 由此可以理解为什么string类型是二进制安全的了。因为它本质上就是个byte数组。当然可以包含任何数据了。 另外String类型可以被部分命令按int处理,比如incr等命令,Redis的其他类型像list,set,sorted set ,hash它们包含的元素与都只能是String类型。

Redis 中的字符为简单动态字符串(simple dynamic string SDS)的抽象类型,并将SDS用作Redis 的默认字符串。当我知道Redis的对象数据类型有5种,有4bits,然后对象的编码类型,占4bits,共10种类型,感觉Redis 也是面向对象的呢!

//type的占5种类型:

/* Object types */
#define OBJ_STRING 0    //字符串对象
#define OBJ_LIST 1      //列表对象
#define OBJ_SET 2       //集合对象
#define OBJ_ZSET 3      //有序集合对象
#define OBJ_HASH 4      //哈希对象
 
// encoding 的10种类型:

//原始表示方式,字符串对象是简单动态字符串
#define OBJ_ENCODING_RAW 0     /* Raw representation */     
//long类型的整数
#define OBJ_ENCODING_INT 1     /* Encoded as integer */         
//字典
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */      
//已经不使用
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */          
//双端链表,已经不使用
#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */  
//压缩列表
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */         
 //整数集合
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */         
//跳跃表和字典
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */      
 //embstr编码的简单动态字符串
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */  
 //由压缩列表组成的双向列表-->快速列表
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */  

#不同类型和编码的对象

REDIS_STRING    REDIS_ENCODING_INT  使用整数值实现的字符串对象。
REDIS_STRING    REDIS_ENCODING_EMBSTR   使用 embstr 编码的简单动态字符串实现的字符串对象。
REDIS_STRING    REDIS_ENCODING_RAW  使用简单动态字符串实现的字符串对象。
REDIS_LIST  REDIS_ENCODING_ZIPLIST  使用压缩列表实现的列表对象。
REDIS_LIST  REDIS_ENCODING_LINKEDLIST   使用双端链表实现的列表对象。
REDIS_HASH  REDIS_ENCODING_ZIPLIST  使用压缩列表实现的哈希对象。
REDIS_HASH  REDIS_ENCODING_HT   使用字典实现的哈希对象。
REDIS_SET   REDIS_ENCODING_INTSET   使用整数集合实现的集合对象。
REDIS_SET   REDIS_ENCODING_HT   使用字典实现的集合对象。
REDIS_ZSET  REDIS_ENCODING_ZIPLIST  使用压缩列表实现的有序集合对象。
REDIS_ZSET  REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现的有序集合对象。


#OBJECT ENCODING 对不同编码的输出

整数  REDIS_ENCODING_INT  "int"
embstr 编码的简单动态字符串(SDS)  REDIS_ENCODING_EMBSTR   "embstr"
简单动态字符串 REDIS_ENCODING_RAW  "raw"
字典  REDIS_ENCODING_HT   "hashtable"
双端链表    REDIS_ENCODING_LINKEDLIST   "linkedlist"
压缩列表    REDIS_ENCODING_ZIPLIST  "ziplist"
整数集合    REDIS_ENCODING_INTSET   "intset"
跳跃表和字典  REDIS_ENCODING_SKIPLIST "skiplist"

上面就是Redis的底层是数据结构,它们支撑起来了这个Key-Value的存储系统。然后我们看看String对应的编码:

字符串对象的编码可以是 INT、RAW 或 EMBSTR。如果保存的是整数值并且可以用long表示,那么编码会设置为INT。当字符串值得长度大于44字节使用RAW,小于等于44字节使用EMBSTR。

Redis在3.0引入EMBSTR编码,这是一种专门用于保存短字符串的一种优化编码方式,这种编码和RAW编码都是用sdshdr简单动态字符串结构来表示。RAW编码会调用两次内存分配函数来分别创建redisObject和sdshdr结构,而EMBSTR只调用一次内存分配函数来分配一块连续的空间保存数据,比起RAW编码的字符串更能节省内存,以及能提升获取数据的速度。

不过要注意!EMBSTR是不可修改的,当对EMBSTR编码的字符串执行任何修改命令,总会先将其转换成RAW编码再进行修改;而INT编码在条件满足的情况下也会被转换成RAW编码。

还要注意一点就是使用String类型是在存储/读取时需要进行序列化/反序列化的!

你可能感兴趣的:(java,数据库,redis)