1、String 类型
这种为最常见的key-value类型存储于redis,通常可用作存储token,在存储是key值最好带有":"冒号方便查找
2、Hash 类型
常用命令:
hget,hset,hgetall 等。
应用场景:
我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:
用户ID,为查找的key,
存储的value用户对象包含姓名name,年龄age,生日birthday 等信息,
如果用普通的key/value结构来存储,主要有以下2种存储方式:
第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,
如:set u001 “李三,18,20010101”
这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,
如:mset user:001:name "李三 "user:001:age18 user:001:birthday “20010101”
虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。
那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,
并提供了直接存取这个Map成员的接口,
如:hmset user:001 name “李三” age 18 birthday “20010101”
也就是说,Key仍然是用户ID,value是一个Map,这个Map的key是成员的属性名,value是属性值,
这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过
key(用户ID) + field(属性标签) 操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。
实现方式:
上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
hash类型,相当于在redis中存储了一个hashMap集合,可用于一个key对应一个hash然后,一个hash又可以对应多个value,实现一个key对应多个属性,可以用于存储对象属性
如
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "118.25.27.188", 6379, 10000,"sa1234",7);
Jedis jedis =jedisPool.getResource();
jedis.hset("15676600197:user","name","张三");
jedis.hset("15676600197:user","age","15");
jedis.hset("15676600197:user","hobby","篮球");
jedis.hset("15676600197:user","sex","男");
System.out.println(jedis.hget("15676600197:user","name"));
Map<String, String> stringStringMap = jedis.hgetAll("15676600197:user");
3、set类型
常用命令:
sadd,srem,spop,sdiff ,smembers,sunion 等。
应用场景:
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
比如在微博应用中,每个人的好友存在一个集合(set)中,这样求两个人的共同好友的操作,可能就只需要用求交集命令即可。
Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实
实现方式:
set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
//set的sadd往set集合中添加数据
jedis.sadd("15676600197:set","2");
jedis.sadd("15676600197:set1","1");
jedis.sadd("15676600197:set1","55");
jedis.sadd("15676600197:set1","3");
jedis.sadd("15676600197:set1","99");
//smembers返回集合中的所有成员。
Set<String> smembers = jedis.smembers("15676600197:set");
Iterator iterator1 =smembers.iterator();
while (iterator1.hasNext()){
String set = (String) iterator1.next();
System.out.println(set);
}
Redis Sdiff 命令返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集。
差集的结果来自前面的 FIRST_KEY ,而不是后面的 OTHER_KEY1,也不是整个 FIRST_KEY OTHER_KEY1..OTHER_KEYN 的差集。
实例:
key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SDIFF key1 key2 key3 = {b,d}
4、sort set类型
有序的集合,可用于点赞排序场景
常用的命令:
1、 zadd(添加) : jedis.zadd(key,score,value);
//第一个为key、22代表排序的值、one 代表value
jedis.zadd("15676600197:zset",22,"one");
jedis.zadd("15676600197:zset",20,"two");
jedis.zadd("15676600197:zset",21,"three");
2、zrange(获取有序集合从小到大)、Zrevrange (从大到小)
Set<String> zrange = jedis.zrange("15676600197:zset", 2, 2);
Iterator iterator2 =zrange.iterator();
while (iterator2.hasNext()){
String s =(String) iterator2.next();
System.out.println(s);
}
下标从0开始
3、zcard(获取集合中元素的数量)
Long zcard = jedis.zcard("15676600197:zset");
System.out.println("数量为:"+zcard);
4、zscore(获取对应key里面对应成员的score值)
Double one = jedis.zscore("15676600197:zset", "one");
System.out.println("one:"+one);
5、list类型
常用命令:
1、lpush(左插入,即从头部插入)
jedis.lpush("15676600197:list","come");
2、lpop(取头部,取走就无)
String lpop = jedis.lpop("15676600197:list");
System.out.println("头部:"+lpop);
3、rpush,rpop(同上相反)
4、lrange(范围取,取完仍在)
List<String> lrange = jedis.lrange("15676600197:list", 0, -1); //取全部
redis的常用命令
jedis.expire(“key”,30); / /给指定的key设置过期时间,可用于redis锁,或者token超时时间,每次调用都会重置时间,这就解决了,用户在操作时token可以连续不实效,在鉴权的同时也续上时间