Redis(请仔细阅读入门到静潜)
说redis之前我们必须了解非关系型数据库 的概念
NoSQL
NoSQL(NoSQL=Not Only SQL),意即"不仅仅是SQL"是一项全新的数据库理念,泛指非关系型数据库。
关系型数据库和非关系型数据可得对比:
【关系型数据库】
关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
**优点**:
1、易于维护:都是使用表结构,格式一致;
2、使用方便:SQL语言通用,可用于复杂查询;
3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
**缺点**:
1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表结构,灵活度稍欠;
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。// 35万/s
【非关系型数据库】
非关系型数据库严格上讲不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
**优点:**
1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
3、高扩展性;
4、成本低:nosql数据库部署简单,基本都是开源软件。
**缺点:**
1、不提供sql支持,学习和使用成本较高;
2、无事务处理;
3、数据结构相对复杂,复杂查询方面稍欠
为什么要用费关系型数据库NoSQL
Why:随着互联网的高速崛起,网站的用户群的增加,访问量的上升,传统数据库上都开始出现了性能瓶颈,web程序不再仅仅专注在功能上,同时也在追求性能。所以NOSQL数据库应运而上,具体表现为对如下三高问题的解决:
【High performance 】- 对数据库高并发读写的需求
web2.0网站要根据用户个性化信息来实时生成动态
页面和提供动态信息,所以基本上无法使用动态页面静态化技术
,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。
关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求 ,
硬盘IO就已经无法承受了。
其实对于普通的BBS网站,往往也存在对高并发写请求的需求,
例如网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,
因此这是一个相当普遍的需求。
【Huge Storage 】- 对海量数据的高效率存储和访问的需求
类似Facebook,twitter,Friendfeed这样的SNS网站,
每天用户产生海量的用户动态,以Friendfeed为例,
一个月就达到了2.5亿条用户动态,对于关系数据库来说,
在一张2.5亿条记录的表里面进行SQL查询,
效率是极其低下乃至不可忍受的。
再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。
【High Scalability && High Availability】- 对数据库的高可扩展性和高可用性的需求
在基于web的架构当中,数据库是最难进行横向扩展的,
当一个应用系统的用户量和访问量与日俱增的时候
,你的数据库却没有办法像web server和app server那样简单的通过
添加更多的硬件和服务节点来扩展性能和负载能力。
对于很多需要提供24小时不间断服务的网站来说,
对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。
主流的NoSQL产品
【NoSQL数据库分类】
- 键值(Key-Value)存储数据库;Map
- 列存储数据库;
- 文档型数据库;
- 图形(Graph)数据库;
以下是详细介绍(仅供了解):
1、【键值(Key-Value)存储】
相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
数据模型: 一系列键值对
优势: 快速查询
劣势: 存储的数据缺少结构化
2、【列存储数据库】
相关产品:Cassandra, HBase, Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储,将同一列数据存在一起
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限
3、【文档型数据库】
相关产品:CouchDB、MongoDB
典型应用:Web应用(与Key-Value类似,Value是结构化的)
数据模型: 一系列键值对
优势:数据结构要求不严格
劣势: 查询性能不高,而且缺乏统一的查询语法
4、【图形数据库】
相关数据库:Neo4J、InfoGrid、Infinite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法。
劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
NoSQL的特点:
NoSQL数据库在大数据存储上具有关系型数据库无法比拟的优势:
1、易扩展
NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。
2、大数据量,高性能
NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。
3、灵活的数据模型
NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的Web2.0时代尤其明显。
4、高可用
NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如Cassandra,HBase模型,通过复制模型也能实现高可用。
综上所述,NoSQL的非关系特性时期成为了后web2.0时代的宠儿,助力大型的web2.0网站的再次起飞,是一项全新的数据库革命性运动。
web1.0---传播信息(静态网页)
web2.0---微博(交互性)-- 功能实现,用户体验(性能--NoSQL)
Redis的概述(了解)
由来
2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG,然而没过多久该公司的创始人Salvatore Sanfilippo便对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身订做一个数据库,并于2009年开发完成,这个数据库就是Redis。
不过Salvatore Sanfilippo并不满足只将Redis用于LLOOGG这一款产品,而是希望更多的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要的代码贡献者Pieter Moordhuis一起继续着Redis的开发,今天。
Salvatore Sanfilippo自己也没想到,短短的几年时间,Redis就拥有了庞大的用户群体。Hacker News在2012年发布了一份数据库的使用情况调查,结果显示有近12%的公司在使用Redis。国内如新浪微博,街旁网,知乎网,国外如GitHub,Stack Overflow,Flickr等都是Redis的用户。
VMware公司从2010年开始赞助Redis的开发,Salvatore Sanfilippo和Pieter Noordhuis也分别在3月和5月加入VMware,全职开发Redis。
什么是Redis
Redis是用C语言开发的一个开源的高性能键值对(Key-Value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的值数据类型如下:
1. 字符串类型 string(常用:json/xml)
2. 散列类型 hash(key--value)map
3. 列表类型 list linkedlist 用户列表
4. 集合类型 set
5. 有序集合类型 sortedset
Redis: 软件–C语言–存储数据
特点:key-value ,内存存储
redis官网下载地址
想体验的话可以自己下载相应的版本使用:
window版的Redis是免安装的,将压缩包解压完成即可使用。
Redis的数据结构
redis中文网站
Redis中的Key值:
Redis中的key值是字符串类型,key值是Redis中数据查询和存储的依据。我们在往Redis中存储数据时,关于key值的命名需要注意以下几点:
key不要太长,最好不要超过1024个字节,这不仅会消耗内存还会降低查找效率
key不要太短,如果太短会降低key的可读性
key命名规范,在项目中key最好有一个统一的命名规范
Redis中的value值:
Redis中的Value值是用来存储具体数据的,常用的数据类型有以下5种(重要):
· 字符串(String)
· 哈希(hash)
· 字符串列表(list)
· 字符串集合(set)
· 有序字符串集合(sorted set)
在日常开发中主要使用比较多的有字符串、哈希、字符串列表、字符串集合四种类型.
其中最为常用的是字符串类型。
常用类型的介绍:
1:字符串类型
2hash类型数据:
Redis中的Hash类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如username、password和age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。
3:列表类型list
list集合: 存取有序(存入时的顺序),有索引,可以重复 ------- 查询快,增删慢
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,
粉丝列表等都可以用Redis的list结构来实现。
List 就是链表,相信略有数据结构知识的人都应该能理解其结构。
使用List结构,我们可以轻松地实现最新消息排行等功能。
List的另一个应用就是消息队列,可以利用List的PUSH操作,
将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。
Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素
概述
帮助理解:
4集合类型set
Redis set对外提供的功能与list类似是一个列表的功能, 特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
和List类型不同的是,Set集合中不允许出现重复的元素
集合类型set的常用命令:
【命令-设置值】sadd key values[value1,value2…]
127.0.0.1:6379> sadd myset zhagnsan lisi wangwu
响应::(integer) 3
【命令-获取值】smembers key
smembers xxx
【命令-删除值】 srem key members[member1、member2…]
5:有序集合sorted Set
应用场景(了解)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。它用来保存需要排序的数据。例如排行榜,一个班的语文成绩,一个公司的员工工资,一个论坛的帖子等。有序集合中,每个元素都带有score(权重),以此来对元素进行排序。它有三个元素:key、member和score。以语文成绩为例,key是考试名称(期中考试、期末考试等),member是学生名字,score是成绩。
有序集合有两大基本用途:排序和聚合
常用命令:
【命令-设置值】zadd key score member[score1 member1,score2 member2…]
【命令-获取集合成员数】zcard key
【命令-查询集合中的元素】zrange key start stop [withscores]
【命令-查询集合中的元素】 zrem key member[member1 … ]
Redis的通用命令:
【查询key】 keys pattern
获取所有与pattern匹配的key,返回所有与该key匹配的keys。*表示任意一个或多个字符,?表示任意一个字符
【根据key值删除】del key1 key2…
删除指定key值的数据
【判断key值是否存在】exists key
判断该key是否存在,1代表存在,0代表不存在
【获取指定key的数据类型】type key
获取指定key的类型。该命令将以字符串的格式返回。 返回的字符串为string、list、set、hash,如果key不存在返回none
Jedis的介绍以及使用
Jedis的介绍:
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、C#、C++、php、Node.js、Go等。
在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用Jedis和Redisson。
在企业中用的最多的就是Jedis,Jedis同样也是托管在github上,
地址:https://github.com/xetorthio/jedis。
下载jedis解压后得到jar包如下:java操作redis数据库API(Jedis)
Jedis的基使用
public class JedisTest {
public static void main(String[] args) {
//1.创建redis核心对象:arg1-host arg2-端口
Jedis jedis = new Jedis("localhost",6379);
//2.存值
jedis.set("name","黑马程序员");
//3.取值
String name = jedis.get("name");
System.out.println(name);
//4.释放资源
jedis.close();
}
}
jedis连接池的使用
Jedis连接池的基本概念:
jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的池化技术–jedisPool。
jedisPool在创建时初始化一些连接资源存储到连接池中,使用jedis连接资源时不需要创建。
而是从连接池中获取一个资源进行redis的操作,使用完毕后,不需要销毁该jedis连接资源,而是将该资源归还给连接池,供其他请求使用。
基本使用演示:
public class JedisPoolTest {
public static void main(String[] args) {
//1 获得连接池配置对象,设置配置项
JedisPoolConfig config = new JedisPoolConfig();
// 1.1 最大连接数
config.setMaxTotal(30);
// 1.2 最大空闲连接数
config.setMaxIdle(10);
//2 获得连接池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
//3 获得核心对象
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4 设置数据
jedis.set("name", "itcast");
//5 获得数据
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
// 虚拟机关闭时,释放pool资源
if(jedisPool != null){
jedisPool.close();
}
}
}
}
so-------------------------->我们需要帮助我们获取工具类(方便我们getJedis哦)
Jedis连接池的工具类
/**
* Jedis工具类
*/
public class JedisUtil {
private static JedisPool jedisPool;
private static int maxtotal;
private static int maxwaitmillis;
private static String host;
private static int port;
//加载配置文件
static {
ResourceBundle jedisPorperties = ResourceBundle.getBundle("jedis");
maxtotal = Integer.valueOf(jedisPorperties.getString("maxtotal"));
maxwaitmillis = Integer.valueOf(jedisPorperties.getString("maxwaitmillis"));
port = Integer.valueOf(jedisPorperties.getString("port"));
host = jedisPorperties.getString("host");
}
//初始化连接池
static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxtotal);
config.setMaxIdle(maxwaitmillis);
jedisPool = new JedisPool(config,host, port);
}
/**
* 获取jedis客户端操作对象
* @return
*/
public static Jedis
() {
return jedisPool.getResource();
}
/**
* 释放资源
* @param jedis
*/
public static void close(Jedis jedis) {
if (null != jedis) {
jedis.close();
}
}
}
Jedis.properties(配置文件)
maxtotal=100(根据需求)
maxwaitmillis=3000(根据需求)
host=127.0.0.1
port=6379
实现加载配置文件的代码实现:(ResourceBundle.java使用说明)
import java.util.ResourceBundle;
public class PropertiesDemo {
// java 专属类 ResourceBundle 对象 jdk 提供
public static void main(String[] args) {
//getBundle源码查询 src路路径下的properties文件 传递文件名默认 .properties 所有不需要写扩展名
String s = ResourceBundle.getBundle("db").getString("driverclass");
String url = ResourceBundle.getBundle("db").getString("url");
String aa = ResourceBundle.getBundle("db").getString("username");
String bb = ResourceBundle.getBundle("db").getString("password");
System.out.println(s);
System.out.println(url);
System.out.println(aa);
System.out.println(bb);
}
}