NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”
是一项全新的数据库理念,泛指非关系型的数据库。
web程序不再仅仅专注在功能上,同时也在追求性能
High performance
对数据库高并发读写的需求
现在数据库并发负载非常高,往往要达到每秒上万次读写请求
关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写 数据请求,硬盘IO就已经无法承受了
Huge Storage
对海量数据的高效率存储和访问的需求
对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的
High Scalability && High Availability-
对数据库的高可扩展性和高可用性的需求
对于很多需要提供24小时不间断服务的网站来说,
对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移
主流产品
键值(Key-Value)存储数据库-redis
主要使用内存, 有两种持久化方案, 速度非常快,
一般做分布式缓存使用
文档型数据库-MongoDB
主要使用硬盘存储, 所以不会担心数据丢失, 速度介于redis和传统数据库之间.
但是mongodb更擅长存储大文本数据, 以及一些非结构化数据,
mongodb比redis的数据类型更加丰富.
例如: 存储小说网站的小说, 存储电商网站的评论等这些数据
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库
官方提供测试数据
50个并发执行100000个请求
读的速度是110000次/s
写的速度是81000次/s
缓存(数据查询、短连接、新闻内容、商品内容等等)
聊天室的在线好友列表
任务队列。(秒杀、抢购、12306等等)
应用排行榜
网站访问统计
数据过期处理(可以精确到毫秒
分布式集群架构中的session分离
获取数据的时候先从redis中获取, 如果获取到数据则直接返回, 就不用访问数据库了
如果获取不到数据, 可以从数据库中查询, 查询到后放入redis中一份, 下回就可以直接从redis中查询到
这样大大降低了数据库的高并发访问压力.
RDB(默认) 分时持久化
可以在配置文件中设定, 多长时间持久化一次, 持久化次数少也就是操作硬盘的次数少,
速度快. 但是如果在没有完成持久化前, 如果服务器断电, 则内存中没有持久化的数据会丢失.
AOF 实时持久化
每次向redis中做增删改操作, 都会将数据持久化到硬盘上, 数据可靠性高, 不会丢失,但是速度慢
链接: https://pan.baidu.com/s/1pS_jPx1WenVaO3nwYRdbSQ 提取码: ac2e
window版的安装及其简单,
解压Redis压缩包完成即安装完毕
双击Redis目录中redis-server.exe可以启动redis服务,Redis服务占用的端口是6379
关闭Redis的控制台窗口就可以关闭Redis服务
编译安装
进入到redis目录
执行命令:
启动
进入到/usr/local/redis-4.0.9/6379/bin目录当中
执行命令: ./redis-server
修改配置文件
把/usr/local/redis-4.0.9/目录下的配置文件复制一份到6379目录下
命令:cp /usr/local/redis-4.0.9/redis.conf /usr/local/redis-4.0.9/6379/bin/
修改配置文件
vim redis.conf
#bind 127.0.0.1 # 将这行代码注释,监听所有的ip地址,外网可以访问
protected-mode no # 把yes改成no,允许外网访问
daemonize yes # 把no改成yes,后台运行
redis是一种高级的key-value的存储系统,其中value支持五种数据类型
Redis的5种数据类型
1. 字符串(String)
2. 哈希(hash)
3. 字符串列表(list)
4. 字符串集合(set)
5. 序字符串集合(sorted set)
key的定义注意点:
key不要太长,最好不要操作1024个字节,这不仅会消耗内存还会降低查找效率
key不要太短,如果太短会降低key的可读性
在项目中,key最好有一个统一的命名规范
在redis-4.0.9/6379/bin目录下输入命令
./redis-cli
概述
设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”
操作
概述
Redis中的Hash类型可以看成具有String Key和String Value的map容器
所以该类型非常适合于存储值对象的信息
操作
概述
在Redis中,List类型是按照插入顺序排序的字符串链表。
和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素
在插入时,如果该键并不存在,Redis将为该键创建一个新的链表
与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除
List中可以包含的最大元素数量是4294967295
操作
lpop key
返回并弹出指定的key关联的链表中的第一个元素,即头部元素
如果该key不存在,返回nil;若key存在,则返回链表的头部元素。
lrange key 遍历该键的所有数据
lrange key 0 -1 返回所有
lrange key 0 2 返回从0开始 0 1 2
概述
在Redis中,我们可以将Set类型看作为没有排序的字符集合
和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作
Set集合中不允许出现重复的元素。
操作
在redis中,可以保证不重复的元素,仍然可以进行排序
概述
Redis的高性能是由于其将所有数据都存储在了内存中
为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化;Redis支持两种方式的持久化,可以单独使用其中一种或将二者结合使用。
一种是RDB方式,一种是AOF方式。
RDB持久化(默认支持,无需配置)
该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘。
AOF持久化
该机制将以日志的形式记录服务器所处理的每一个写操作
在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。
无持久化
我们可以通过配置的方式禁用Redis服务器的持久化功能
这样我们就可以将Redis视为一个功能加强版的memcached了
redis可以同时使用RDB和AOF
RDB持久化机制优点
一旦采用该方式,那么你的整个Redis数据库将只包含一个文件
这对于文件备份而言是非常完美的
RDB持久化机制缺点
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
快照触发条件
客户端执行命令save和bgsave会生成快照;
根据配置文件save m n规则进行自动快照;
主从复制时,从库全量复制同步主库数据,此时主库会执行bgsave命令进行快照;
客户端执行数据库清空命令FLUSHALL时候,触发快照;
客户端执行shutdown关闭redis时,触发快照;
RDB持久化机制的配置
在redis.conf进行修改配置
save m n
配置快照(rdb)促发规则,格式:save
save 900 1 900秒内至少有1个key被改变则做一次快照
save 300 10 300秒内至少有10个key被改变则做一次快照
save 60 10000 60秒内至少有10000个key被改变则做一次快照
#关闭该规则使用save “ ”
dbfilename dump.rdb
rdb持久化存储数据库文件名,默认为dump.rdb
stop-write-on-bgsave-error yes
yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。
rdbchecksum yes
在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
dir “./”
数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限
rdbcompression yes
是否开启RDB文件压缩,该功能可以节约磁盘空间
AOF概述
当redis存储非临时数据时,为了降低redis故障而引起的数据丢失,redis提供了AOF(Append Only File)持久化,
从单词意思讲,将命令追加到文件。AOF可以将Redis执行的每一条写命令追加到磁盘文件(appendonly.aof)中
在redis启动时候优先选择从AOF文件恢复数据。由于每一次的写操作,redis都会记录到文件中,所以开启AOF持久化会对性能有一定的影响
AOF持久化数据丢失更少,其消耗内存更少(RDB方式执行bgsve会有内存拷贝)
开启AOF持久化
默认情况下,redis是关闭了AOF持久化,开启AOF通过配置appendonly为yes开启
将appendonly修改为yes,开启aof持久化机制,默认会在目录下产生一个appendonly.aof文件
我们修改配置文件或者在命令行直接使用config set修改,在用config rewrite同步到配置文件。通过客户端修改好处是不用重启redis,AOF持久化直接生效
config get appendonly:查询配置状态
config set appendonly yes:修改配置
config rewrite:写入到redis.conf中
配置
appendfsync:always 每执行一次更新命令,持久化一次
appendfsync:everysec 每秒钟持久化一次
appendfsync:no 不持久化
通过aof-use-rdb-preamble配置参数控制,yes则表示开启,no表示禁用,默认是禁用的,可通过config set修改。
获取密码
config get requirepass
设置密码
config set requirepass 123456
当有密码的时候登录时需要密码登录
auth 密码
取消密码
config set requirepass ‘’
使用Jedis操作redis需要导入jar包如下:
jedis常用API
new Jedis(host, port)
创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口
set(key,value)
设置字符串类型的数据
get(key)
获得字符串类型的数据
hset(key,field,value)
设置哈希类型的数据
hget(key,field)
获得哈希类型的数据
lpush(key,values)
设置列表类型的数据
lpop(key)
列表左面弹栈
rpop(key)
列表右面弹栈
del(key)
删除指定的key
jedis的基本操作
public void testJedis(){
//1 设置ip地址和端口
Jedis jedis = new Jedis("localhost", 6379);
//2 设置数据
jedis.set("name", "fmjava");
//3 获得数据
String name = jedis.get("name");
System.out.println(name);
//4 释放资源
jedis.close();
}
jedis连接池的基本概念
jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的池化技术
示例代码
public void testJedisPool(){
//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", "fmjava");
//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();
}
}
}
Spring-data-redis是spring大家族的一部分
提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装
RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>5.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.8.1version>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
<version>1.7.2.RELEASEversion>
dependency>
dependencies>
redis.host=192.168.0.108
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:*.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
bean>
beans>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSet() {
redisTemplate.boundValueOps("name").set("joker");
}
@Test
public void testGet() {
String name = (String) redisTemplate.boundValueOps("name").get();
System.out.println("name=" + name);
}
@Test
public void testDelete() {
redisTemplate.delete("name");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestList {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testLpush() {
redisTemplate.boundListOps("myListKey").leftPush("001");
redisTemplate.boundListOps("myListKey").leftPush("002");
redisTemplate.boundListOps("myListKey").leftPush("003");
redisTemplate.boundListOps("myListKey").leftPush("004");
}
@Test
public void testRpush() {
redisTemplate.boundListOps("myListKey").rightPush("001");
redisTemplate.boundListOps("myListKey").rightPush("002");
redisTemplate.boundListOps("myListKey").rightPush("003");
redisTemplate.boundListOps("myListKey").rightPush("004");
}
@Test
public void testRange() {
List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
for (String s : myListKey) {
System.out.println("value=" + s);
}
}
@Test
public void testDelete() {
redisTemplate.delete("myListKey");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestHash {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testPut() {
redisTemplate.boundHashOps("keyname1").put("name", "zs");
redisTemplate.boundHashOps("keyname1").put("age", "20");
redisTemplate.boundHashOps("keyname1").put("phone", "121");
redisTemplate.boundHashOps("keyname1").put("email", "[email protected]");
}
@Test
public void testGetOne() {
String name = (String)redisTemplate.boundHashOps("keyname1").get("name");
System.out.println("name =" + name);
}
@Test
public void testGetAll() {
//获取所有的entries
Map<String, String> testHash = (Map<String, String>)redisTemplate.boundHashOps("keyname1").entries();
Set<Map.Entry<String, String>> entries = testHash.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key=" + entry.getKey());
System.out.println("value=" + entry.getValue());
}
}
@Test
public void testDeleteOne() {
redisTemplate.boundHashOps("keyname1").delete("name");
}
@Test
public void testDeleteAll() {
redisTemplate.delete("keyname1");
}
}
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private Integer age;
private char sex;
public Person(String name, Integer age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestObject {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setObject(){
Person person = new Person("joker", 20, '男');
redisTemplate.boundValueOps("person").set(person);
}
@Test
public void getObject(){
Person person=(Person)redisTemplate.boundValueOps("person").get();
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestObject {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setObject(){
Person person = new Person("joker", 20, '男');
Person person1 = new Person("joker1", 21, '男');
Person person2 = new Person("joker1", 21, '男');
Person person3 = new Person("joker1", 21, '男');
ArrayList<Person> personArrayList=new ArrayList<>();
personArrayList.add(person);
personArrayList.add(person1);
personArrayList.add(person2);
personArrayList.add(person3);
/*分业务*/
redisTemplate.boundHashOps("userService").put("person",personArrayList);
}
@Test
public void getObject(){
List<Person> people=(List<Person>) redisTemplate.boundHashOps("userService").get("person");
System.out.println(people);
}
}
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.4version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.9.4version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.4version>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
dependency>
redis.host=192.168.0.108
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
spring/applicationContext-redis.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:/properties/*.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
bean>
beans>