1、Redis是什么
Redis最直观的认识就是个key-value数据库,可以存储多类型的数据。
百度百科解释:Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
2、Redis有啥用
Redis安装于硬盘之上,数据存储在内存之中。且redis在执行命令时是单线程的,又是存内存访问,没有线程竞争,没有CPU的资源消耗,访问速度快啊。项目中为了减少数据库的访问,数据查询效率都会用到Redis;如系统投票,抢红包,购物车等功能点都会使用redis来强化对应功能。
3、Redis怎么用
redis提供了五种数据类型的存储:string、hash、list、set、zset
(1)string:字符串,数字,二进制。这些值单个value不超过512M
使用示例:
public static void testStr() throws InterruptedException {
// jedis简单理解是redis提供的一个客户端来操作redis。项目中不使用jedis,会使用连接池或者其它封装
Jedis jedis = new Jedis("192.168.1.85",6379);
jedis.auth("redis");
try{
// 测试string类型 像redis中设置一条key为stringkey,value为11的数据
jedis.set("stringkey","11");
// 获取stringkey对应的value
String stringkey = jedis.get("stringkey");
System.out.println("获取的stringkey:"+stringkey);
// 设置有过期时间的 stringkey3 value为33 nx:redis中不存在时才插入值,ex:过期时间单位为秒,1:过期时间为1ex,即:1秒
String set = jedis.set("stringkey3", "33", "nx", "ex", 1);
String stringkey3 = jedis.get("stringkey3");
System.out.println("获取的stringkey3:"+stringkey3);
// 休眠4秒等到stringkey3过期
Thread.sleep(2000);
System.out.println("获取失效后的的stringkey3:"+jedis.get("stringkey3"));
// 批量设值
jedis.mset("name","wu","age","18");
System.out.println("获取的value:"+jedis.mget("name","age"));
jedis.incr("age");
System.out.println("获取的age加一:"+jedis.get("age"));
jedis.decr("age");
System.out.println("获取的age减一:"+jedis.get("age"));
jedis.incrBy("age",5);
System.out.println("获取的age自定义加:"+jedis.get("age"));
jedis.decrBy("age",5);
System.out.println("获取的age自定义减:"+jedis.get("age"));
// 字符串的追加、截取、长度获取
jedis.set("testString","zhongguo");
System.out.println("获取的testString:"+jedis.get("testString"));
// 中文占3字节
jedis.append("testString","你好");
System.out.println("获取的testString:"+jedis.get("testString"));
Long testString = jedis.strlen("testString");
System.out.println("获取的testString:"+testString);
String testString1 = jedis.substr("testString", 0, 2);
System.out.println("获取的testString:"+testString1);
jedis.close();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
if(Objects.nonNull(jedis)){
jedis.close();
}
}
}
测试结果:
获取的stringkey:11
获取的stringkey3:33
获取失效后的的stringkey3:null
获取的value:[wu, 18]
获取的age加一:19
获取的age减一:18
获取的age自定义加:23
获取的age自定义减:18
获取的testString:zhongguo
获取的testString:zhongguo你好
获取的testString:14
获取的testString:zho
string类型使用最多的地方应该就是incrby了。
(2)hash:类似于数据库中的一个表,二维结构,大多存储对象。如:用户表:一个用户为一条数据,用户下有账号,姓名、密码,手机号码等等属性。
public static void testHash(){
// jedis简单理解是redis提供的一个客户端来操作redis。项目中不使用jedis,会使用连接池或者其它封装
Jedis jedis = new Jedis("192.168.1.85",6379);
jedis.auth("redis");
try{
// 对用户1进行设值
jedis.hset("user:1", "name", "zhangsan");
jedis.hset("user:1", "realname", "张三");
jedis.hset("user:1", "age", "18");
jedis.hset("user:1", "phone", "132********");
// 批量对用户2进行设值
Map map = new HashMap();
map.put("name", "lisi");
map.put("realname", "李四");
map.put("age","81");
map.put("phone","131********");
jedis.hmset("user:2", map);
// 获取用户1单个值
System.out.println(jedis.hget("user:1","name"));
// 批量获取用户2的值
System.out.println(jedis.hmget("user:2","name","realname","age","phone"));
// 判断字段是否存在
System.out.println(jedis.hexists("user:1","name"));
// 获取张三的所有属性
System.out.println(jedis.hkeys("user:1"));
// 获取张三所有的属性值
System.out.println(jedis.hvals("user:1"));
// 获取张三的属性和值
System.out.println(jedis.hgetAll("user:1"));
// 让张三年龄加2
jedis.hincrBy("user:1","age",2);
// 获取张三的属性和值
System.out.println(jedis.hgetAll("user:1"));
jedis.close();
}finally {
if(Objects.nonNull(jedis)){
jedis.close();
}
}
}
测试结果
zhangsan
[lisi, 李四, 81, 131********]
true
[name, phone, age, realname]
[zhangsan, 张三, 18, 132********]
{name=zhangsan, phone=132********, age=18, realname=张三}
{name=zhangsan, phone=132********, age=20, realname=张三}
string类型虽然也可以实现hash的效果,假如都往redis存一个用户信息,string方式需要设置4个key+value,而hash的话只需要合理设计好key之后一个key+value即可,相比之下节约内存。
(3)list 列表:用于存储有序的字符串,和java里面的list原理类似,一个有序的列表。
public static void testList(){
// jedis简单理解是redis提供的一个客户端来操作redis。项目中不使用jedis,会使用连接池或者其它封装
Jedis jedis = new Jedis("192.168.1.85",6379);
jedis.auth("redis");
try{
// 向空列表从左到右插入值
jedis.lpush("listkey","A","B","D");
// 从左到右遍历列表
System.out.println(jedis.lrange("listkey",0,-1));
jedis.lpush("listkey","1","3","2");
System.out.println(jedis.lrange("listkey",0,-1));
jedis.rpush("listkey","e","h","k");
System.out.println(jedis.lrange("listkey",0,-1));
// 在listkey的列表中,往D的前面插入一个value为666
jedis.linsert("listkey",Client.LIST_POSITION.BEFORE,"D","666");
System.out.println(jedis.lrange("listkey",0,-1));
String listkey = jedis.rpop("listkey");
System.out.println("取出右边的第一个值:"+listkey);
System.out.println(jedis.lrange("listkey",0,-1));
String listkey2 = jedis.lpop("listkey");
System.out.println("取出左边的第一个值:"+listkey2);
System.out.println(jedis.lrange("listkey",0,-1));
jedis.close();
}finally {
if(Objects.nonNull(jedis)){
jedis.close();
}
}
}
测试结果
[D, B, A]
[2, 3, 1, D, B, A]
[2, 3, 1, D, B, A, e, h, k]
[2, 3, 1, 666, D, B, A, e, h, k]
取出右边的第一个值:k
[2, 3, 1, 666, D, B, A, e, h]
取出左边的第一个值:2
[3, 1, 666, D, B, A, e, h]
(4)set 集合:和list的区别,无序性且不能重复。list是用一根管子装数据,而set则是用一个球装数据;可以利用set的特性球多个集合的交、并、差集。
public static void testMap(){
// jedis简单理解是redis提供的一个客户端来操作redis。项目中不使用jedis,会使用连接池或者其它封装
Jedis jedis = new Jedis("192.168.1.85",6379);
jedis.auth("redis");
try{
// 微信用户1的微信好友
jedis.sadd("wechat:1:friends","张三","李四","王五");
// 获取微信用户1 的好友列表
Set smembers = jedis.smembers("wechat:1:friends");
Iterator iterator = smembers.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println("用户1的好友"+next);
}
// 微信用户2的微信好友
jedis.sadd("wechat:2:friends","张三","王子","麻子");
// 找用户1和用户的共同好友
Set sinter = jedis.sinter("wechat:2:friends", "wechat:1:friends");
Iterator iterator1 = sinter.iterator();
while(iterator1.hasNext()){
String next = iterator1.next();
System.out.println("用户1和用户2 的的好友"+next);
}
jedis.close();
}finally {
if(Objects.nonNull(jedis)){
jedis.close();
}
}
}
(5)、zset :有序且有排名的set集合。
public static void testzMap(){
// jedis简单理解是redis提供的一个客户端来操作redis。项目中不使用jedis,会使用连接池或者其它封装
Jedis jedis = new Jedis("192.168.1.85",6379);
jedis.auth("redis");
try{
// 记录用户的微信好友数
// jedis.zadd("user:wechat",302,"李四");
jedis.zadd("user:wechat",300,"张三");
jedis.zadd("user:wechat",298,"麻子");
jedis.zadd("user:wechat",296,"麻子1");
jedis.zadd("user:wechat",212,"麻子3");
jedis.zadd("user:wechat",211,"麻子4");
jedis.zadd("user:wechat",277,"麻子65");
jedis.zadd("user:wechat",2987,"麻子6");
jedis.zadd("user:wechat",6000,"麻子7");
jedis.zadd("user:wechat",66,"麻子9");
Set zrange = jedis.zrange("user:wechat", 0, -1);
Iterator iterator = zrange.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println("微信好友数排名"+next);
}
jedis.close();
}finally {
if(Objects.nonNull(jedis)){
jedis.close();
}
}
}
list,set,zset的区别
list:允许重复,使用索引下标实现有序,应用于消息队列
set:不允许重复,无序,应用于集合统计(微信好友数统计)
zset:不允许重复,采用分值实现有序,常实现排行榜。
后面慢慢学习redis的应用。