NoSql数据库—Redis纯干货

1.NoSql数据库

1.1 what(什么是NoSQL数据库)

    NoSql全称 not only sql ,非关系型数据库。他采用简单、高效的数据格式(例如key-value等)将数据存储于内存中,极大地提高了数据的访问速度。可以作为关系型数据库的一个很好的补充但不能代替关系型数据库。

1.2 why(为什么要使用NoSQL数据库)

    传统关系型数据库一般用来存储重要信息,应对普通的业务是没有问题的。但是,随着互联网的高速发展,传统的关系型数据库在应付超大规模,超大流量以及高并发的时候力不从心。
    为了解决高并发、高可扩展(集群)、高可用(不能宕机)、大数据存储问题而产生的数据库解决方案,就是NoSql数据库。

1.3 where(应用场景?)

    Nosql数据库相较于传统关系型数据库,最大的优点就是存储简单、访问速度快
    根据它的特点主要有以下几点应用:
        缓存
        分布式集群架构中的session分离
        任务队列(秒杀、抢购、12306等等)
        应用排行榜(SortedSet)
        网站访问统计
        数据过期处理(expire)

1.4 How(如何使用?)

    接下来的整篇文章,都在介绍如何使用。

关系型数据库和非关系数据的比较

存储方式存储结构存储规范存储扩展查询方式事务性能
关系二维表结构化数据(预先定义列结构)存储于表中(避免重复、结构清晰)纵向扩展(操作的性能瓶颈可能涉及多个表,需要通过提高计算机的性能来克服)结构化的查询方式(SQL)支持-遵循ACID规则低(维护数据的一致性付出了巨大的代价)
非关系数据集(键值,文档等)动态结构(适应数据类型、和结构变化)存储于数据集中(可重复、易读写)横向扩展(天然分布式)key-value查询(类似map)支持-遵循BASE原则高(数据松散且存储于内存中)

常见的关系型数据库

键值(Key-Value)存储数据库
相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB。
典型应用:内容缓存,主要用于处理大量数据的高访问负载。
数据模型:一系列键值对
优势:快速查询
劣势:存储的数据缺少结构化

列存储数据库
相关产品:Cassandra, HBase, Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储,将同一列数据存在一起
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限

文档型数据库
相关产品:CouchDB、MongoDB
典型应用:Web应用(与Key-Value类似,Value是结构化的)
数据模型:一系列键值对
优势:数据结构要求不严格
劣势:查询性能不高,而且缺乏统一的查询语法

图形(Graph)数据库
相关数据库:Neo4J、InfoGrid、Infinite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法。
劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。

2.Reids

2.1 简介

    Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库(nosql),应用在缓存。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型有5种
    如下:
        字符串类型 (String)
        散列类型(hash)
        列表类型(List)
        集合类型(set)
        有序集合类型(SortedSet)

2.2 安装(单机)

1>下载

官网地址:http://redis.io/

2.安装c语言编译环境gcc

 yum -y install gcc-c++

3.上传tar包,解压缩 tar-zxvf 目录
4.进行编译 : cd到解压目录 ,输入命令 make
5.执行安装(指定安装目录)

make install PREFIX=/usr/local/redis	

在这里插入图片描述
6.进入安装目录,查看是有bin目录存在

2.3 服务/客户端的连接、关闭

服务端-前端启动:

		bin目录下: ./redis-server 

在这里插入图片描述
这种启动方式后我们就不能进行其他的操作了, Ctrl+C 即可退出。

服务端-后台启动(推荐):
第一步:把解压目录中的/redis.conf复制到安装目录/usr/local/redis/bin目录下
第二步:使用vim命令修改redis.conf配置文件 将daemonize no修改为daemonize yes
在这里插入图片描述
第三步:输入启动命令 (bin目录下)

	   ./redis-server redis.conf

第四步:检查redis进程

		ps -ef|grep redis

客户端的启动
1> 使用Redis-cli建立连接:

        bin目录下: ./redis-cli 

    默认连接localhost运行在6379端口的redis服务。

		完整命令如下:./redis-cli -h 192.168.25.131 -p 6379

在这里插入图片描述

2>使用redis的桌面程序建立连接
    下载安装Redis-Deskop-manager即可,这里就不演示了。

退出客户端cli 连接
    第一种:
        [root@localhost bin]# ./redis-cli
        127.0.0.1:6379> quit
    第二种:
        [root@localhost bin]# ./redis-cli
        127.0.0.1:6379> exit
    第三种:CTR+C

退出redis服务
    第一种:通过连接上客户端进行关闭,使用shutdown 命令。
在这里插入图片描述
    第二种:使用 kill 命令。
        找到对应的redis的进程id 然后使用命令:(pid为进程id) kill -9 pid

2.4 常用的数据类型

1>String
命令格式
设置值set key value
获取值get key
设置获取值(返回该值的原始值)getset key value
删除数据(通用)del key
递增1incr key
递增指定长度incrby key 递增值
递减1decr key
递增指定长度decrby key 递增值
追加字符串(返回追加后的长度)append key value
查询所有key(通用)keys *
判断key是否存在(1,0)exists key

在这里插入图片描述

2>Hash
命令格式
设置值 [多个]hset key field value [field1 value1 field2 valued…]
获取值hget key field
获取值 [多个]hmget key field [field1 field2…]
获取所有的field valuehgetall key
删除指定fieldhdel key field
删除指定key(通用)del key
递增/减(num的正负)hincr key field num
判断field是否存在hexits key field
获取key中field的个数hlen key
获取key中所有的fieldhkeys key
获取key中所有的valuehvals key

在这里插入图片描述

3>List
List是有顺序可重复(数据结构中的:双链表,队列)
可作为链表 ,从左添加元素  也可以从右添加元素。
命令格式
插入(左/右)lpush/rpush key value[value1 value2 …]
查看lrange key start end (start:从0开始,end可以为负数,表示倒数第几个,0 -1表示查看所有)
弹出(删除)lpop/rpop key (从左/右删除,并返回被删除的元素)
获取个数llen key
添加如果key存在lpushx/rpushx key value [value1 value2 …]
删除(从哪开始删除几个value)lrem key num value 例如:lrem key 2 1 表示从左边开始删除2个1,若num为0则表示全部删除、num为负数 表示从右开始删除]
插入到指定位置lset key index value (注意从0开始)

在这里插入图片描述

4>Set
命令格式
添加sadd key value1 [value2 value3…]
删除srem key value1 [value2 value3…]
查看smembers key
判断是否存在sismember key value
差级运算sdiff key1 key2 (key2相对于key1的差, 结果和key1、key2顺序有关)
交集运算sinter key1 key2
并集运算sunion key1 key2
得到元素的数量scard key
随机返回指定数量成员srandmember key [count] (不写count默认返回一个)
设置新集合保存差值、并集、交集sdiffstore/sinterstore/sunionstore key key1 key2

在这里插入图片描述

5>ZSet
有顺序,不能重复,如果重复会覆盖,适合做排行榜
命令格式
添加zadd key 分数1 值1 分数2 值2 …
获取分数zscore key value
获取value的数量zcard key
范围查找zrange/zrevrange key start end [withscores] (分数可选择是否显示,range从小到大,rerange 从大到小)
删除zrem key value1 [value2 value3 …]
按照排名的顺序删除zremrangebyrank key start end
按照分数范围删除zremrangebyscore key 分数1 分数2
统计分数之间的value个数zcount key 分数1 分数2 (注意分数1>=分数2)
添加分数zincrby key 分数 value

2.5通用操作

命令格式
获取所有的keykeys *
判断key是否存在exists key
key重命名rename old new
删除keydel key [key1 key2 …]
设置key的过期时间expire key time (time : 0 负数,可以理解为立刻删除)
查看当前key所剩时间ttl key (-1表示永久,-2表示不存在)
持久化keypersist key (ttl查看时间为-1)
查看当前key的类别type key
清空当前库full all

2.7Reids特性

1>多数据库

Redis中共有16个数据库,索引从0开始,默认是选择第0个
        切换数据库: select index[0-15]
        移动到某库:move key index

2>事务机制

    相比于传统的关系型数据库来说,Redis的事务并不突出,所以了解即可。
        开启:multi
        提交:exec
        回滚:discard

3>Redis持久化

    Redis的高性能源于其数据保存于内存中,所以存取都是相当快,但是当断电时,内存中的数据便会丢失,此时我们需要将数据持久化 内存->硬盘,下次启动的时候,redis会依据持久化的信息做数据恢复。

1.RDB   快照形式  (定期将当前时刻的数据保存磁盘中)会产生一个dump.rdb文件
	特点:会存在数据丢失,性能较好,数据备份。
2.AOF   append only file ,日志形式 (所有对redis的操作命令记录在aof文件中),恢复数据,重新执行一遍即可。
	特点:每秒保存,数据比较完整,耗费性能。	

RDB:快照模式默认开启,默认会将dump.rdb文件保存在redis安装目录根目录下。
     优点:
        1.只包含一个文件
        2.性能最大化
    缺点:
        1.指定间隔保存,宕机时总有来不及保存的文件。
        2.如果指定间隔时间过长,保存的停顿时间很大(Reids是单线程的)

在redis.conf中配置RDB的保存时间间隔:
在这里插入图片描述
AOF:是采取日志记录的方式、可以每秒,每次修改,进行数据持久化。
     优势:
          1.数据安全性高,数据丢失概率小。
          2.采用追加写入,日志过大,自动重写(瘦身)
          3.格式清晰,易于修改日志文件
     劣势:
        文件大,持久化次数频繁、运行效率低于RDB
修改redis.conf 配置文件,开启AOF
在这里插入图片描述
主要是修改:
     1.开启aof appendobly yes
     2.appendsync 选中同步策略, always或者eyerysec
     修改后需要停掉redis,重启服务。

注意:默认使用rdb方式,但是如果两都开启了,会使用aof

3.Jedis

Jedis即:Redis的Java客户端API,使用方式也很简单

			<!-- Redis客户端 -->
			<dependency>
				<groupId>redis.clients</groupId>
				<artifactId>jedis</artifactId>
				<version>xxxxxxx</version>
			</dependency>

3.1常用API

	// string类型操作
	@Test
	public void string_test() {
		// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
		Jedis jedis = new Jedis("192.168.25.131", 6379);
		// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
		// 添加设置字符串
		jedis.set("hello", "word");
		String result = jedis.get("hello");
		System.out.println(result); // world
		// 添加数字,自增长
		jedis.set("id", "1");
		String id = jedis.get("id");
		System.out.println(id); // 1
		System.out.println(jedis.incr("id")); // 2
		System.out.println(jedis.get("id")); // 2
		// 第三步:关闭Jedis
		jedis.close();
	}
     
     //hash类型的操作
	@Test
	public void hash_test() {
		// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
		Jedis jedis = new Jedis("192.168.25.131", 6379);
		// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
		// 添加map的redis的hash中
		Map<String, String> map = new HashMap<>();
		map.put("name", "faker");
		map.put("grade", "100");
		jedis.hmset("skt", map);
		// 获取指定field值
		System.out.println(jedis.hget("skt", "name")); // faker
		// 获取个field对应的值
		jedis.hmget("skt", "name", "grade").forEach(System.out::println); // faker 100
		// 设置增长
		System.out.println(jedis.hincrBy("skt", "grade", 20)); // 120
		jedis.close();
	}
    
    // list类型的操作
	@Test
	public void list_test() {
		// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
		Jedis jedis = new Jedis("192.168.25.131", 6379);
		// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
		// 分别从左右添加
		jedis.lpush("list", "1", "2", "3");
		jedis.rpush("list", "x", "y", "z");
		// lrange 获取指定范围的值
		jedis.lrange("list", 0, -1).forEach(System.out::println); // 3 2 1 x y z
		// pop 弹出,删除指定值
		System.out.println(jedis.rpop("list")); // z
		// lset 在指定位设置指定值
		jedis.lset("list", 0, "first");
		jedis.lrange("list", 0, -1).forEach(System.out::println); // first 2 1 x y
		jedis.close();
	}
	
	// set类型的操作
	@Test
	public void set_test() {
		// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
		Jedis jedis = new Jedis("192.168.25.131", 6379);
		// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
		// sadd添加值
		jedis.sadd("set", "1", "faker", "2");
		// smembers获取所有值
		jedis.smembers("set").forEach(System.out::println); // 2 faker 1
		// srem 删除指定value
		jedis.srem("set", "1");
		// sismember判断指定vlaue是否存在
		System.out.println(jedis.sismember("set", "1")); // false
		jedis.close();
	}
	
	// zset类型的操作
	@Test
	public void zset_add() {
		// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
		Jedis jedis = new Jedis("192.168.25.131", 6379);
		// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
		Map<String, Double> zset = new HashMap<>();
		zset.put("faker", 100d);
		zset.put("clearlove", 99d);
		zset.put("uzi", 99d);
		// 向zset中插入数据
		jedis.zadd("zset", zset);
		// 获取zset中的所有数据
		Set<Tuple> withScores = jedis.zrangeWithScores("zset", 0, -1);
		withScores.forEach(e -> {
			System.out.println(e.getElement() + "-------" + e.getScore());
			// clearlove-------99.0 uzi-------99.0 faker-------100.0
		});
		// 获取指定value的分数
		System.out.println(jedis.zscore("zset", "faker")); // 100.0
		jedis.close();
	}

    通过上述代码可以看出,使用Jedis操作Reids首先要获取连接对象(Jedis),这和传统的数据库获取connection对象是一样的,Jedis也为我们提供了连接池的方式,在程序中更推荐大家使用连接池方式。

	@Test
	public void testJedisPool() throws Exception {
		// 第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。
		JedisPool jedisPool = new JedisPool("192.168.25.131", 6379);
		// 第二步:从JedisPool中获得Jedis对象。
		Jedis jedis = jedisPool.getResource();
		// 第三步:使用Jedis操作redis服务器。
		jedis.set("jedis", "test");
		String result = jedis.get("jedis");
		System.out.println(result); //jedispool
		// 第四步:操作完毕后关闭jedis对象,连接池回收资源。
		jedis.close();
		// 第五步:关闭JedisPool对象。
		jedisPool.close();
	}

3.2 Spring整合Redis

Redis和Spring的整合十分的简单,我们只需要使用Spring容器管理JedisPool就可以了

1.首先加入相关的spring、jedis依赖

        <!--此处为了方便直接引入springmvc的配置文件-->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.16.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>

2.配置

	<!-- 配置redis连接池 -->
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="192.168.25.131"></constructor-arg>
		<constructor-arg name="port" value="6379"></constructor-arg>
	</bean>

3.测试

@Test
	public void redis_spring_test() {
		// 1.首先加载spring的配置文件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		// 2.获取连接池对象
		JedisPool pool = applicationContext.getBean(JedisPool.class);
		// 3.获取Jedis对象
		Jedis jedis = pool.getResource();
		jedis.set("hello", "world");
		System.out.println(jedis.get("hello")); // world
		jedis.close();
		pool.close();
	}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值