一、概念
1、 Remote Dictionary Server (远程字典服务器)
2、是一款高性能的( Key/Values)分布式内存数据库,支持数据持久化(定期把内存里数据存储到硬盘),支持多种数据类型:字符、列表、散列、集合一支持master-salve模式数据备份.
set key名value值 //存储1个key值
mset key名列表 //存储多个key值
get key名 //获取指定key值
mget //获取多个key值
select数据库编号0-15 //切换库
keys* //显示所有key名
keys a? //显示指定key名
exists key名 //测试key名是否存在
ttl key名 //查看key生存时间
type key名 //查看key类型
move key名库编号 //移动key到指定库
expire key名数字 //设置key有效时间
del key名 //删除指定的key
flushall //删除内存里所有key
flushdb //删除所在库的所有key
save //保存所有key到硬盘
shutdown //停止服务
二、数据类型
1、String类型
string
–是Redis 中最基本的数据类型, -它能存储任何形式的字符串,包括二进制数据 -可以用其存储用户的邮箱、JSON化的对象甚至是一张图片-一个字符串类型允许存储的数据的最大容量是512MB -字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是组织字符串的形式不同
使用场景
计数器:许多运用都会使用redis作为计数的基础工具,他可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他的数据源。
如:视频播放数系统就是使用redis作为视频播放数计数的基础组件
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* set key value -> 存入键值对
* get key -> 根据键取出值
* incr key -> 把值递增1
* decr key -> 把值递减1
* del key -> 根据键删除键值对
* setex key timeout value -> 存入键值对,timeout表示失效时间,单位s
* ttl key->可以查询出当前的key还剩余多长时间过期 // 如果设置了过期时间 过期了返回-2,如果没设置过期时间会返回-1
* setnx key value -> 如果key已经存在,不做操作, 如果key不存在,直接添加
*/
@Test
public void test() {
JedisPool pool = new JedisPool("localhost", 6379);
Jedis redis = pool.getResource();
redis.set("name", "Frank");
redis.set("age", "19");
redis.incr("age");
redis.decr("age");
redis.del("name");
redis.setex("hobby", 20, "play");
redis.setnx("name", "Frank");
redis.mset("salary", "2000", "name", "Frank");
redis.mget("salary", "name");
redis.close();
pool.destroy();
}
stringRedisTemplate.opsForValue().set("M_KEY", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间
stringRedisTemplate.boundValueOps("M_KEY").increment(-1);//val做-1操作
stringRedisTemplate.opsForValue().get("M_KEY")//根据key获取缓存中的val
stringRedisTemplate.boundValueOps("M_KEY").increment(1);//val +1
stringRedisTemplate.getExpire("M_KEY");//根据key获取过期时间
stringRedisTemplate.getExpire("M_KEY",TimeUnit.SECONDS);//根据key获取过期时间并换算成指定单位
stringRedisTemplate.delete("M_KEY");//根据key删除缓存
stringRedisTemplate.hasKey("M_KEY");//检查key是否存在,返回boolean值
stringRedisTemplate.opsForSet().add("M_KEY", "1","2","3");//向指定key中存放set集合
stringRedisTemplate.expire("M_KEY",1000 , TimeUnit.MILLISECONDS);//设置过期时间
stringRedisTemplate.opsForSet().isMember("M_KEY", "1")//根据key查看集合中是否存在指定数据
stringRedisTemplate.opsForSet().members("M_KEY");//根据key获取set集合
@Test
public void test2() {
stringRedisTemplate.opsForValue().set("age", "100");
System.out.println(stringRedisTemplate.opsForValue().get("age"));
stringRedisTemplate.opsForValue().increment("age");
stringRedisTemplate.opsForValue().decrement("age");
stringRedisTemplate.delete("age");
//设置对应的key过期时间
//第一个参数为 key,第二个为时间数,第三个为单位
stringRedisTemplate.expire("age", 30, TimeUnit.SECONDS);
System.out.println(stringRedisTemplate.opsForValue().setIfPresent("name", "Taoshijie"));
stringRedisTemplate.opsForValue().set("name", "xiaofei", 20, TimeUnit.SECONDS);
System.out.println(stringRedisTemplate.getExpire("name"));
}
2、Hash
-
hash
-是一个string类型的field和value的映射表 -一个key可对应多个field,一个field对应一个value -将一个对象存储为hash类型,较于每个字段都存储成string类型更能节省内存
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* hset key hashkey hashvalue -> 存入一个hash对象
* hget key hashkey -> 根据hash对象键取去值
* hexists key hashkey -> 判断hash对象是含有某个键
* hdel key hashkey -> 根据hashkey删除hash对象键值对
*/
@Test
public void jedis() {
JedisPool pool = new JedisPool("localhost", 6379);
Jedis redis = pool.getResource();
redis.hset("user", "name", "taotao");
redis.hexists("user", "name");
redis.hdel("user", "name");
redis.close();
pool.destroy();
}
@Test
public void test() {
stringRedisTemplate.opsForHash().put("user", "name", "JkBo");
stringRedisTemplate.opsForHash().get("user", "name");
System.out.println(stringRedisTemplate.opsForHash().hasKey("user", "name"));
stringRedisTemplate.opsForHash().delete("user", "name");
}
3、List
List
列表类型(list)可以存储一个有序的字符串队列·先进后出 一个key可以有多个值
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* rpush key value -> 往列表右边添加数据
* lrange key start end -> 范围显示列表数据,全显示则设置0 -1
* lpush key value -> 往列表左边添加数据
* lpop key -> 弹出列表最左边的数据
* rpop key -> 弹出列表最右边的数据
* llen key -> 获取列表长度
*/
@Test
public void jedis() {
JedisPool pool = new JedisPool("localhost", 6379);
Jedis redis = pool.getResource();
// 这个key 为list 名字
redis.rpush("name", "zhangsan");
redis.rpush("name", "lisi");
redis.rpush("name", "taotao");
redis.rpush("name", "wangwu");
//[zhangsan, lisi, taotao, wangwu] 以张三为中轴线向左添加
redis.lpush("name", "dafei");
//[dafei, zhangsan, lisi, taotao, wangwu]
System.out.println(redis.lrange("name", 0, -1));
redis.lpop("name");
redis.rpop("name");
redis.llen("name");
redis.close();
pool.destroy();
}
@Test
public void test() {
//往列表右边添加数据
stringRedisTemplate.opsForList().rightPush("myList","zhangs");
stringRedisTemplate.opsForList().rightPush("myList","lis");
stringRedisTemplate.opsForList().rightPush("myList","wangw");
stringRedisTemplate.opsForList().rightPush("myList","xiaofei");
//范围显示列表数据,全显示则设置0 -1
System.out.println(stringRedisTemplate.opsForList().range("myList", 0, 1));
//往列表左边添加数据
stringRedisTemplate.opsForList().leftPush("myList","daTfei");
//弹出列表最右边的数据
stringRedisTemplate.opsForList().rightPop("myList");
//弹出列表最左边的数据
stringRedisTemplate.opsForList().leftPop("myList");
//获取列表长度
System.out.println(stringRedisTemplate.opsForList().size("myList"));
}
4、Set
set
集合中的每个元素都是唯一的,且没有顺序
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* sadd key value -> 往set集合中添加元素
* smembers key -> 列出set集合中的元素
* srem key value -> 删除set集合中的元素
* spop key count -> 随机弹出集合中的元素
*/
@Test
public void jedis() {
JedisPool pool = new JedisPool("localhost", 6379);
Jedis redis = pool.getResource();
redis.sadd("mySet", "zhangsan");
redis.sadd("mySet", "lisi");
redis.sadd("mySet", "wangwu");
redis.sadd("mySet", "xiaofei");
redis.srem("mySet", "xiaofei");
redis.spop("mySet", 2);
}
/**
* add(K key, V... values) 向变量中批量添加值
* redisTemplate.opsForSet().add("setValue","A","B","C","B","D","E","F");
* <p>
* members(K key) 获取变量中的值
* Set set = redisTemplate.opsForSet().members("setValue");
* System.out.println("通过members(K key)方法获取变量中的元素值:" + set);
* <p>
* size(K key) 获取变量中值的长度
* long setLength = redisTemplate.opsForSet().size("setValue");
* System.out.println("通过size(K key)方法获取变量中元素值的长度:" + setLength);
* <p>
* randomMember(K key) 随机获取变量中的元素
* Object randomMember = redisTemplate.opsForSet().randomMember("setValue");
* System.out.println("通过randomMember(K key)方法随机获取变量中的元素:" + randomMember);
* <p>
* randomMembers(K key, long count) 随机获取变量中指定个数的元素
* List randomMembers = redisTemplate.opsForSet().randomMembers("setValue",2);
* System.out.println("通过randomMembers(K key, long count)方法随机获取变量中指定个数的元素:" + randomMembers);
* <p>
* isMember(K key, Object o) 检查给定的元素是否在变量中
* boolean isMember = redisTemplate.opsForSet().isMember("setValue","A");
* System.out.println("通过isMember(K key, Object o)方法检查给定的元素是否在变量中:" + isMember);
* <p>
* move(K key, V value, K destKey) 转移变量的元素值到目的变量
* boolean isMove = redisTemplate.opsForSet().move("setValue","A","destSetValue");
* if(isMove){
* set = redisTemplate.opsForSet().members("setValue");
* System.out.print("通过move(K key, V value, K destKey)方法转移变量的元素值到目的变量后的剩余元素:" + set);
* set = redisTemplate.opsForSet().members("destSetValue");
* System.out.println(",目的变量中的元素值:" + set);
* }
* <p>
* pop(K key) 弹出变量中的元素
* Object popValue = redisTemplate.opsForSet().pop("setValue");
* System.out.print("通过pop(K key)方法弹出变量中的元素:" + popValue);
* set = redisTemplate.opsForSet().members("setValue");
* System.out.println(",剩余元素:" + set)
* <p>
* remove(K key, Object... values) 批量移除变量中的元素
* long removeCount = redisTemplate.opsForSet().remove("setValue","E","F","G");
* System.out.print("通过remove(K key, Object... values)方法移除变量中的元素个数:" + removeCount);
* set = redisTemplate.opsForSet().members("setValue");
* System.out.println(",剩余元素:" + set);
* <p>
* scan(K key, ScanOptions options) 匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
* //Cursor<Object> cursor = redisTemplate.opsForSet().scan("setValue", ScanOptions.NONE);
* Cursor<Object> cursor = redisTemplate.opsForSet().scan("setValue", ScanOptions.scanOptions().match("C").build());
* while (cursor.hasNext()){
* Object object = cursor.next();
* System.out.println("通过scan(K key, ScanOptions options)方法获取匹配的值:" + object);
* }
* <p>
* difference(K key, Collection<K> otherKeys) 通过集合求差值
* List list = new ArrayList();
* list.add("destSetValue");
* Set differenceSet = redisTemplate.opsForSet().difference("setValue",list);
* System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定集合中变量不一样的值:" + differenceSet);
* <p>
* difference(K key, K otherKey) 通过给定的key求2个set变量的差值
* differenceSet = redisTemplate.opsForSet().difference("setValue","destSetValue");
* System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定变量不一样的值:" + differenceSet);
* <p>
* differenceAndStore(K key, K otherKey, K destKey) 将求出来的差值元素保存
* redisTemplate.opsForSet().differenceAndStore("setValue","destSetValue","storeSetValue");
* set = redisTemplate.opsForSet().members("storeSetValue");
* System.out.println("通过differenceAndStore(K key, K otherKey, K destKey)方法将求出来的差值元素保存:" + set);
* <p>
* differenceAndStore(K key, Collection<K> otherKeys, K destKey) 将求出来的差值元素保存
* redisTemplate.opsForSet().differenceAndStore("setValue",list,"storeSetValue");
* set = redisTemplate.opsForSet().members("storeSetValue");
* System.out.println("通过differenceAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的差值元素保存:" + set);
* <p>
* distinctRandomMembers(K key, long count) 获取去重的随机元素
* set = redisTemplate.opsForSet().distinctRandomMembers("setValue",2);
* System.out.println("通过distinctRandomMembers(K key, long count)方法获取去重的随机元素:" + set);
* <p>
* intersect(K key, K otherKey) 获取2个变量中的交集
* <p>
* intersect(K key, Collection<K> otherKeys)
* set = redisTemplate.opsForSet().intersect("setValue",list);
* System.out.println("通过intersect(K key, Collection<K> otherKeys)方法获取交集元素:" + set);
* <p>
* intersectAndStore(K key, K otherKey, K destKey) 获取2个变量交集后保存到最后一个参数上
* redisTemplate.opsForSet().intersectAndStore("setValue","destSetValue","intersectValue");
* set = redisTemplate.opsForSet().members("intersectValue");
* System.out.println("通过intersectAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);
* <p>
* intersectAndStore(K key, Collection<K> otherKeys, K destKey) 获取多个变量的交集并保存到最后一个参数上
* redisTemplate.opsForSet().intersectAndStore("setValue",list,"intersectListValue");
* set = redisTemplate.opsForSet().members("intersectListValue");
* System.out.println("通过intersectAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set);
* <p>
* union(K key, K otherKey) 获取2个变量的合集
* set = redisTemplate.opsForSet().union("setValue","destSetValue");
* System.out.println("通过union(K key, K otherKey)方法获取2个变量的合集元素:" + set);
* <p>
* union(K key, Collection<K> otherKeys) 获取多个变量的合集
* set = redisTemplate.opsForSet().union("setValue",list);
* System.out.println("通过union(K key, Collection<K> otherKeys)方法获取多个变量的合集元素:" + set);
* <p>
* unionAndStore(K key, K otherKey, K destKey) 获取2个变量合集后保存到最后一个参数上
* redisTemplate.opsForSet().unionAndStore("setValue","destSetValue","unionValue");
* set = redisTemplate.opsForSet().members("unionValue");
* System.out.println("通过unionAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);
* <p>
* unionAndStore(K key, Collection<K> otherKeys, K destKey) 获取多个变量的合集并保存到最后一个参数上
* redisTemplate.opsForSet().unionAndStore("setValue",list,"unionListValue");
* set = redisTemplate.opsForSet().members("unionListValue");
* System.out.println("通过unionAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set);
*/
@Test
public void test() {
// 向指定集合存放 元素
stringRedisTemplate.opsForSet().add("mySet", "ToTik", "xaiofei", "dafei");
System.out.println(stringRedisTemplate.opsForSet().members("mySet"));
System.out.println(stringRedisTemplate.opsForSet().size("mySet"));
System.out.println(stringRedisTemplate.opsForSet().randomMember("mySet"));
stringRedisTemplate.opsForSet().pop("mySet");
}
5、sorted_set
zset
. Redis有序集合和无序集合一样也是string类型元素的集合且不允许重复的成员。 ·不同的是每个元素都会关联一个数字的分数。redis通过分数来为集合中的成员进行从小到大的排序。 ·有序集合的成员是唯一的,但分数却可以重复。
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* zadd key score column -> 存入分数和名称
* zincrby key score column -> 偏移名称对应的分数
* zrange key start end -> 按照分数升序输出名称
* zrevrange key start end -> 按照分数降序输出名称
* zrank key name -> 升序返回排名
* zrevrank key name -> 降序返回排名
* zcard key -> 返回元素个数
*/
@Test
public void jedis() {
JedisPool pool = new JedisPool("localhost", 6379);
Jedis redis = pool.getResource();
redis.zadd("ZSet", 1000, "a");
redis.zadd("ZSet", 2000, "b");
redis.zadd("ZSet", 900, "c");
redis.zadd("ZSet", 3000, "d");
System.out.println(redis.zrange("ZSet", 0, -1));
System.out.println(redis.zrevrange("ZSet", 0, -1));
System.out.println(redis.zrank("ZSet", "d"));
System.out.println(redis.zrevrank("ZSet", "d"));
System.out.println(redis.zcard("ZSet"));
redis.close();
pool.destroy();
}
@Test
public void test() {
stringRedisTemplate.opsForZSet().add("Zset","a",1000);
stringRedisTemplate.opsForZSet().add("Zset","b",3000);
stringRedisTemplate.opsForZSet().add("Zset","c",2000);
stringRedisTemplate.opsForZSet().add("Zset","d",4000);
stringRedisTemplate.opsForZSet().incrementScore("Zset","a",5000);
System.out.println(stringRedisTemplate.opsForZSet().zCard("Zset"));
System.out.println(stringRedisTemplate.opsForZSet().range("Zset", 0, -1));
System.out.println(stringRedisTemplate.opsForZSet().reverseRange("Zset", 0, -1));
}
三、交集、差集、并集
交集:取出两个集合重复的元素 sinter key key 这里的key为集合名
并集:去除两个集合重复的元素,合并到一起 sunion key key
差集:取出左边集合在右边集合不存在的元素 sdiff key key
四、Redis 最适合的场景
(1)会话缓存(Session Cache)
(2)全页缓存(FPC)
(3)队列
(4)排行榜/计数器
String:一般做一些复杂的计数功能的缓存;
Hash:存储二维数据或对象;
List:可实现队列,栈及有序的数据存储;
Set:常用于黑名单,微信抽奖等功能,应用场景多变;
SortedSet:做排行榜应用,取TOPN操作;延时任务;做范围查找
五、Redis 优点, 缺点, 定位
定位:
redis定位是缓存, 提高数据读写速度, 减轻对数据库存储与访问压力
优点:
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
缺点:
-
由于是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小。虽然redis本身有key过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。
-
如果进行完整重同步,由于需要生成rdb文件,并进行传输,会占用主机的CPU,并会消耗现网的带宽。不过redis2.8版本,已经有部分重同步的功能,但是还是有可能有完整重同步的。比如,新上线的备机。
-
修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中,redis不能提供服务