Redis学习笔记之二:Redis的数据存储结构

来源:互联网 发布:华针数据恢复 编辑:程序博客网 时间:2024/05/21 11:14

 Redis与Mysql等关系型数据库的第一点区别就是Redis的数据存储结构,Mysql等关系型数据库以表的形式存放数据,而Redis提供Key-Value形式的存储格式。与Mysql等数据库的第二点区别就是数据结构不同,Mysql等关系型数据库支持整数、浮点数、字符串、文本、时间戳等等,而Redis的Key-Value格式中Key只能是String类型,但Redis的Value类型有5种,Value可以为String,List,散列类型(Map),Set(集合类型),ZSet(有序集合类型)。这一点看起来好像Mysql要更胜一筹,但你需要知道Redis的源码仅仅只有3万行左右,相比Mysql,这已经很不错了。


      Redis的Value类型有5种,其中String类型是基础,其他四种格式包含的只能是String类型,且这5种格式不能有相互嵌套。什么意思? 例如,在列表中的各项只能是字符串,而不能是列表、map、集合,而对于集合等其他数据结构来讲也是一样。


     前面也说过,在Redis中是使用指令来进行数据操纵的。Redis一共提供了100个指令,上面所说的各个类型都需要不同的指令来操纵。这指令听起来好像很多,但其实真正使用的只有一部分,而且这些执行很简单,非常容易记忆。例如,将字符串存储到Redis中使用set指令。


可以看到,键入set指令会有一个提示,然后继续输入:


当然,还有适用于Key的指令,看一百遍不如动手练一练,现在可以打开电脑上的Redis输入Redis-cli -h host -p port实际练一练。如果你没有安装Redis,也是有办法的,进入到Redis官网,点击try it下方的链接,然后会跳转到下面如图所示的页面,然后在绿色框内输入指令体会一下吧。


Redis的部分指令

 顺带提一下,Redis的指令与SQL一样,是不区分大小写的,但后面的Key-Value是区分大小写的。下面命令均使用String类型练习。

   1、EXISTS 这个指令用于判断指定的Key是否存在,存在返回1,不存在则返回0


EXISTS是可以跟多个Key的,key存在则返回值+1,否则+0,但如果跟多个Key,那就不能知道到底哪个Key存在,哪个Key不存在,例如上图的test与test2.

   2、DEL,(DELETE)这个指令用于删除Key,同样是可以跟多个Key值的,会返回删除键的个数。


   3、TYPE,这个指令类似于Linux中的typeof和java中的instanceof操作符,用于返回Key对应的Value类型,只能跟一个Key。如果对应的Key不存在,返回为none。


   4、EXPIRE,Redis常常用作缓存服务器,自然缓存是有时效的,可以使用这个指令设置时间,单位是秒。只能跟一个Key,返回值为1表示设置成功,返回为0表示设置失败或者Key不存在,所以不能使用这个指令来判断Key是否存在。


   5、TTL,这个指令用于查看Key的有效时间(Time To Live),单位秒。只能跟一个Key,如果Key不存在返回-2,如果Key没有使用EXPIRE设置时间,则返回-1.


   6、PERSIST,这个命令用于取消Key的失效时间,取消成功则返回1,失败则返回0(Key本身就是永久的或者Key不存在)


   7、Redis还提供了更精确的时间控制,使用指令PEXPIRE设置,单位是毫秒,同时使用PTTL查看,单位毫秒。除此之外,与EXPIRE和TTL没有什么不同。


   8、KEYS pattern。这个指令用于返回有哪些Key,后面pattern支持正则。?表示匹配一个字符,*表示0或者多个,转义字符使用\转义。


   ps:除了KEYS指令,其他上面的TYPE、DEL等均不支持正则匹配,例如:


   看完上述几个指令应该体会到Redis的简单吧,下面看一下Redis的Java客户端吧。

Redis的Java客户端

   测试代码如下:
package org.yamikaze.redis.test;import redis.clients.jedis.Jedis;import java.util.Set;/** * 测试Java的Client * @author yamikaze */public class TestClient {    public static void main(String[] args) {        //host填写对应的域名或者ip,端口不填默认6379        Jedis client = new Jedis("192.168.1.99");        String key = "test";        String key1 = "test2";        String value = "yamikaze";        setValue(client, key, value);        /**         * 对应EXISTS指令,但区别在于参数只有一个时返回Boolean,多参数时返回Long         */        client.exists(key);        client.exists(key, key1);        /**         * 对应DEL指令,返回值为Long         */        client.del(key);        client.del(key, key1);        /**         * 对应TYPE指令,返回值为String         */        setValue(client, key, value);        String type = client.type(key);        System.out.println(type);        /**         * 对应EXPIRE以及TTL,PERSIST指令         */        client.expire(key, 10);        Long seconds = client.ttl(key);        System.out.println(seconds);        client.persist(key);        /**         * pexpire有两个版本,参数分别为String, int和String,long         *                  int版本已被弃用         */        client.pexpire(key, 10000L);        Long millSeconds = client.pttl(key);        System.out.println(millSeconds);        client.persist(key);        /**         * 对应KEYS指令         */        setValue(client, key1, value);        Set<String> keys = client.keys("test*");        for(String k : keys) {            //test test2            System.out.println(k);        }    }    private static void setValue(Jedis client, String key, String value) {        client.set(key, value);    }}
   可以看到Redis的客户端与用到的指令一样,这就减小了Redis的学习难度。

Redis的Key-Value是否允许为Null

   我们知道,在Java中,Hashtable对Key以及Value是有限制的,Key和Value均不能为null,那Redis中的Key-Value呢?


   可以看到,set这个指令是有参数限制的,Key-Value必须同时存在,这儿可能看不出是否允许null,那我们可以用代码测试一个null时的情况。


   从图可以看出,set时Value不能为null,Key也不能为null,那我们测试下在服务器存入Key-null,使用代码拉取看看是什么情况。

package org.yamikaze.redis.test;import redis.clients.jedis.Jedis;/** * 从Redis服务器拉取Key-Value为test-null的数据 * @author yamikaze */public class GetKeyValue {    public static void main(String[] args) {        Jedis client = new Jedis("192.168.1.99");        String key = "test";        String value = client.get(key);        //false        System.out.println(value == null);        //null字符串        System.out.println(value);    }}
   以上说明,在客户端往服务端设置数据时不能为null值,但服务器可以设置为null(字符串形式的null),而从服务器拉取数据时只有Key不存在,则会返回null。所以往服务器set数据时,需要判空(Key和Value都要),get数据时也要判空(Key判空是因为不能向Redis发送null,而服务器对值判空是程序需要,避免NPE)。如果Redis存储的是null-null,则要用null字符串取数据。


参考资料

   《Redis入门指南》