您的位置:首页 > 数据库 > Redis

为什么要用redis

2020-07-05 16:04 295 查看

1 redis是NOSQL

1.1.什么是NOSQL

NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。

1.1.1. NOSQL和关系型数据库比较

优点:

  1. 成本:
    nosql数据库简单易部署,基本都是开源软件,不需要像使用oracle那样花费大量成本购买使用,相比关 系型数据库价格便宜。
  2. 查询速度:
    nosql数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查询速度远不及nosql 数据库。
  3. 存储数据的格式:
    nosql的存储格式是key,value形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
  4. 扩展性:
    关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。

缺点:

维护的工具和资料有限,因为nosql是属于新的技术,不能和关系型数据库10几年的技术同日而语。不提供对sql的支持,如果不支持sql这样的工业标准,将产生一定用户的学习和使用成本。不提供关系型数据库对事务的处理。

1.1.4. 总结

关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,让NoSQL数据库对关系型数据库的不足进行弥补。一般会将数据存储在关系型数据库中,在nosql 数据库中备份存储关系型数据库的数据。

1.2 什么是Redis

在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。

3什么时候使用redis

  • 存储 缓存 用的数据;
  • 需要高速读/写的场合使用它快速读/写;

3.1缓存

在日常对数据库的访问中,读操作的次数远超写操作,比例大概在1:9到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样速度明显就会快上不少,并且会极大减小数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用 Redis 存储一些常用和主要的数据,比如用户登录的信息等。一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:

  • 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存;
  • 该业务数据是读操作多,还是写操作多?如果写操作多,频繁需要写入数据库,也没有必要使用缓存;
  • 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要;
  • 第一次读取数据的时候,读取 Redis 的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入 Redis 中;
  • 第二次以及以后需要读取数据时,就会直接读取 Redis,读到数据后就结束了流程,这样速度就大大提高了。

3.2 高速读/写的场合

在如今的互联网中,越来越多的存在高并发的情况,比如天猫双11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流失重则数据库瘫痪,服务宕机,而这样的场合都是不允许的!

  • 当一个请求到达服务器时,只是把业务数据在 Redis 上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速响应的需求
  • 但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完 Redis 的读/写之后,会去判断该高速读/写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

4 Java客户端 Jedis

Jedis: 一款java操作redis数据库的工具.

使用步骤:

1. 下载jedis的jar包

2. 使用

//1. 获取连接

Jedis jedis = new Jedis("localhost",6379);

//2. 操作

jedis.set("username","zhangsan");

//3. 关闭连接

jedis.close();

Jedis操作各种redis中的数据结构

1) 字符串类型 string

set

get

//1. 获取连接

Jedis jedis = new Jedis();//如果使用空参构造,默认值 "localhost",6379端口

//2. 操作

//存储

jedis.set("username","zhangsan");

//获取

String username = jedis.get("username");

System.out.println(username);

//可以使用setex()方法存储可以指定过期时间的 key value

jedis.setex("activecode",20,"hehe");//将activecode:hehe键值对存入redis,并且20秒后自动删除该键值对

//3. 关闭连接

jedis.close();

2) 哈希类型 hash :map格式

hset

hget

hgetAll

//1. 获取连接

Jedis jedis = new Jedis();//如果使用空参构造,默认值 "localhost",6379端口

//2. 操作

// 存储hash

jedis.hset("user","name","lisi");

jedis.hset("user","age","23");

jedis.hset("user","gender","female");

// 获取hash

String name = jedis.hget("user", "name");

System.out.println(name);

 

// 获取hash的所有map中的数据

Map<String, String> user = jedis.hgetAll("user");

// keyset

Set<String> keySet = user.keySet();

for (String key : keySet) {

//获取value

String value = user.get(key);

System.out.println(key + ":" + value);

}

//3. 关闭连接

jedis.close();

3) 列表类型 list :linkedlist格式。支持重复元素

lpush / rpush

lpop / rpop

lrange start end : 范围获取

//1. 获取连接

Jedis jedis = new Jedis();//如果使用空参构造,默认值 "localhost",6379端口

//2. 操作

// list 存储

jedis.lpush("mylist","a","b","c");//从左边存

jedis.rpush("mylist","a","b","c");//从右边存

// list 范围获取

List<String> mylist = jedis.lrange("mylist", 0, -1);

System.out.println(mylist);

// list 弹出

String element1 = jedis.lpop("mylist");//c

System.out.println(element1);

String element2 = jedis.rpop("mylist");//c

System.out.println(element2);

// list 范围获取

List<String> mylist2 = jedis.lrange("mylist", 0, -1);

System.out.println(mylist2);

//3. 关闭连接

jedis.close();

4) 集合类型 set :不允许重复元素

sadd

smembers:获取所有元素

//1. 获取连接

Jedis jedis = new Jedis();//如果使用空参构造,默认值 "localhost",6379端口

//2. 操作

 

// set 存储

jedis.sadd("myset","java","php","c++");

// set 获取

Set<String> myset = jedis.smembers("myset");

System.out.println(myset);

//3. 关闭连接

jedis.close();

5) 有序集合类型 sortedset:不允许重复元素,且元素有顺序

zadd

zrange

//1. 获取连接

Jedis jedis = new Jedis();//如果使用空参构造,默认值 "localhost",6379端口

//2. 操作

// sortedset 存储

jedis.zadd("mysortedset",3,"亚瑟");

jedis.zadd("mysortedset",30,"后裔");

jedis.zadd("mysortedset",55,"孙悟空");

// sortedset 获取

Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);

System.out.println(mysortedset);

//3. 关闭连接

jedis.close();

5 一句话总结

当出现高并发,io瓶颈,数据缓存考虑下redis吧,当然会增加系统复杂度,但是他是值得的。


有兴趣关注公众号:一分云

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: