进阶学习之Redis

一、NoSQL概述

1、NoSQL(NoSQL = Not Only SQL),意思是不仅仅是SQL,是一项全新的数据库理念, 泛指非关系型的数据库。

2、NoSQL数据库的四大分类
① 键值(Key-Value)存储数据库
相关产品:Tokyo Cabinet/Tyrant、Redis、Voldemort 、Berkeley DB
典型应用:内容缓存,主要用于处理大最数据的高访问负载
数据模型:一系列键值对
优势:快速查询
劣势:存储的数据缺少结构化
② 列存储数据库
相关产品:Cassandra、HBase、Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储, 将同一列数据存在一起
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限
③ 文挡型数据库
相关产品:Couch DB、MongoDB
典型应用:Web应用(与Key-Value 类似, Value 是结构化的}
数据模型:一系列键值对
优势:数据结构要求不严格
劣势:查询性能不高,而且缺乏统一的查询语法
④ 图形(Graph )数据库
相关数据库:Neo4J、lnfoGrid、Infnite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法
劣势:要对整个图做计算才能得出结果,不容易做分布式的主民群方案

3、NoSQL特点
在大数据存取上具备关系型数据库无法比拟的性能优势,例如:
① 易扩展
NoSQL数据库种类繁多, 但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展
② 大数据量,高性能
NoSQL数据库都具有非常高的读写性能,尤其在大数据量下, 同样表现优秀。这得益于它的无关系性,数据库的结构简单
③ 灵活的数据模型
NoSQL无需事先为要存储的数据建立字段, 随时可以存储自定义的数据格式。
④ 高可用
NoSQL在不太影响性能的情况下,就可以方便的实现高可用的架构。比如Cassandra、HBase模型,通过复制模型也能实现高可用

二、Redis概述

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

2、应用场景
① 级存(数据查询、短连接、新闻内容、商品内容等等)【最多使用】
⑤ 聊天室的在线好友列表
③ 任务队列(秒杀、抢购、12306等等)
④ 应用排行榜
⑤ 网站访问统计
⑥ 数据过期处理(可以精确到毫秒)
⑦ 分布式集群架构中的session分类

三、Redis在Linux上的安装

1、安装Redis编译的c环境:yum install gcc-c++
2、将redis-2.6.16.tar.gz上传到Linux系统中
3、解压到/usr/local下:tar -zxvf redis-2.6.16.tar.gz -C /usr/local
4、进入redis-2.6.16目录中将.c文件编译为.o文件:make
5、在redis-2.6.16目录中使用make PREFIX=/usr/local/redis install命令安装 Redis到/usr/local/redis中(安装完后在/usr/local/redis/bin 下有几个可执行文件:redis-benchmark表示性能测试工具,redis-check-aof表示aof文件修复工具,redis-check-dump表示快照持久化文件,redis-cli表示命令行客户端,redis-conf表示Redis配置文件,redis-server表示Redis服务器启动命令)
6、redis启动需要一个配置文件,可以修改端口号等信息。拷贝redis-2.6.16中的redis.conf到安装目录redis中:cp redis.conf /usr/local/redis/bin,然后vim redis.conf,设置daemonize yes修改为后台进程模式,然后./redis-server redis.conf启动

7、如需远程连接redis,需配置redis端口6379在linux防火墙中开发

/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
/etc/rc.d/init.d/iptables save

8、前端模式启动:在/redis/bin下执行命令:redis-server,启动后窗口不能关闭,窗口关闭(ctrl+c)就认为redis也关闭了(类似Tomcat通过bin下的startup.bat的方式)
9、后端模式启动:修改redis.conf配置文件,将redis.conf文件中的daemonize从no修改成yes,表示服务器启动了但不会占据控制台窗口,然后执行命令:redis-server ../redis.conf
10、使用命令查看6379端口是否启动:ps -ef | grep -i redis
11、Redis停止:强制结束进程会导致数据丢失,正确应该是向Redis发送shutdown命令:./usr/local/redis/bin/redis-cli shutdown,或者kill -9 28832杀死进程

四、Redis使用

1、连接客户端
在Redis的安装目录中有redis 的客户端,即redis-cli,它是Redis自带的基于命令行的Redis客户端:./bin/redis-cli -h ip地址 -p 端口
或者在目录下使用默认ip和端口号:./redis-cli
退出:quit
中文显示:./redis-cli --raw

2、向Redis 服务器发送命令
redis-cli连上redis 服务后,就可以在命令行发送命令。
① ping:测试客户端与Redis 的连接是否正常,如果连接正常会收到回复PONG
② set/get:使用set和get可以向redis设置数据、获取数据

set name itcastzs
get name

③ del:删除指定key的内容:del name
④ keys:查看当前库中所有的key值:keys *

五、Redis的数据结构

1、Redis的数据结构介绍
redis是一种高级的key-value的存储系统,其中value支持五种数据类型。
① 字符串(String)
② 哈希(Hash)
③ 字符串列表(List)
④ 字符串集合(Set)
⑤ 有序字符串集合(Sorted set )

2、存储String
字符串类型是Redis中最为基础的数据存储类型,它在Redis 中是二进制安全的,这便意味着该类型存入和获取的数据相同。在Redis中字符串类型的Value最多可以容纳的数据长度是512M 。
① 赋值命令:set key value
设定key持有指定的字符串value,如果该key存在则进行覆盖操作,总是返回ok
示例:set company itcast
② 取值命令:get key
获取key 的value,如果与该key关联的value不是String 类型,redis将返回错误信息,因为get命令只能用于获取String类型的value,如果该key不存在,返回nil
示例:get company
③ 先获取该key的值,然后在设置该key的值:getset key value
示例:getset company itheima
④ 删除命令:del key
示例:del company
⑤ 数值增减
incr key:将指定的key的value原子性的递增1,如果该key不存在,其初始值为0,在incr之后其值为1;如果value的值不能转成整型,如hello,则该操作将执行失败并返回相应的错误信息
decr key:将指定的key的value原子性的递减1,如果该key不存在,其初始值为0,在decr之后其值为-1;如果value的值不能转成整型,如hello,则该操作将执行失败并返回相应的错误信息
⑥ 其他命令

incrby key increment		-- 将指定的key的value原子性增加increment,如果该key 不存在, 其初始值为0 ,在incrby之后,该值为increment;如果该值不能转成整型,如hello,则失败并返回错误
decrby key decrement		-- 将指定的key的value原子性减少decrement,如果该key不存在, 其初始值为0,在decrby之后,该值为-decrement;如果该值不能转成整型,如hello,则失败并返回错误
append key value		-- 拼凑字符串。如果该key存在,则在原有的value后追加该值;如果该 key不存在,则重新创建一个key/value

3、存储Hash
Redis 中的Hash类型可以看成具有String Key 和String Value 的map容器,所以该类型非常适合于存储值对象的信息,如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。
① 赋值命令:
hset key field value:为指定的key设定field/value对(键值对)
示例:hset myhash name zhangsan
hmset key field value [field2 value2 ... ] :设置key中的多个filed/value
示例:hset myhash name zhangsan pwd 123
② 取值命令:
hget key field :返回指定的key中的field的值
示例:hget myhash name
hmget key fileds:获取key中的多个filed的值
示例:hget myhash name pwd
hgetall key:获取key 中的所有filed-vaule
示例:hgetall myhash
③ 删除命令
hdel key field [field ... ] : 可以删除一个或多个字段,返回值是被删除的字段个数
示例:hdel myhash name
del key:删除整个list
示例:del myhash
④ 增加数字:hincrby key field increment
设置key中filed 的值增加increment,如age增加20
示例:hincrby myhash age 20
⑤ 其他命令

hexists key field		-- 判断指定的key中的filed是否存在
hlen key		-- 获取key所包含的field的数量
hkeys key		-- 获得key的所有的field
hvals key		-- 获得key的所有的value

4、存储List
在Redis中,List 类型是按照插入顺序排序的字符串链表,和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元索。在插入时, 如果该键并不存在,Redis 将为该键创建一个新的链表。与此相反,如果链表中所有的元索均被移除,那么该键也将会被从数据库中删除。List 中可以包含的最大元素数量是4294967295 。
从元素插入和删除的效率视角来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中己经存储了百万条记录,该操作也可以在常量时间内完成。但是如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。
① 两端添加:
lpush key values[value1 value2 ... ]:在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。插入成功, 返回元素的个数
rpush key values[value1 value2... ]:在该list:的尾部添加元素
② 查看元素:range key start end
获取链表中从start到end 的元素的值,start、end 从0 开始计数,也可为
负数, 若为-1则表示链表尾部的元索,-2则表示倒数第二个, 依次类推……
示例:range mylist 0 5
③ 两端弹出:
lpop key:返回并弹出指定的key关联的链表中的第一个元素,即头部元素。如果该key 不存在,返回nil
rpop key:从尾部弹出元素。
④ 获取列表中元素个数:llen key
⑤ 其他命令

lpushx key value		-- 仅当参数中指定的key存在肘,向关联的list的头部捕入value,如果不存在,将不进行插入。
rpushx key value		-- 在该list的尾部添加元素
Irem key count value		-- 删除count个值为value的元素,如果count 大于0,从头向尾遍历并删除count个值为value的元素;如果count小于0,则从尾向头遍历并删除-count个值为value的元素;如果count 等于0,则删除链表中所有等于value 的元索。
lset key index value		-- 设置链表中的index的脚标的元素值,0 代表链表的头元素,-1代表链表的尾元素,操作链表的脚标不存在则抛异常。
Iinsert key [before I after] pivot value		-- 在pivot元素前或者后插入value这个元素
rpoplpush mylist1 mylist2		-- 将mylist1链表中的尾部元素弹出并添加到mylist2的头部。[循环操作]

5、存储Set
在Redis中, 我们可以将Set 类型看作为没有排序的字符集合,和List 类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元索是否存在等操作。需要说明的是, 这些操作的时间复杂度为o(1),即常量时间内完成次操作。Set 可包含的最大元索数量是4294967295 。
和List 类型不同的是,Set 集合中不允许出现重复的元索,这一点和C++标准库中的set容器是完全相同的。和List 类型相比,Set 类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets 之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成, 因此效率极高,而且
也节省了大量的网络IO开销。
① 添加元素:sadd key values[valuel value2...]
向set 中添加数据,如果该key 的值己有则不会重复添加
② 删除元素:srem key members[memberl member2... ]
③ 获取集合中元素
smembers key : 获取set 中所有的成员
sismember key member : 判断参数中指定的成员是否在该set中,1表示存在,0 表示不存在或有该key,本身就不存在(无论集合中有多少元素都可以急速地返回结果)
④ 集合的差集运算A-B:sdiff key1 key2 ...
返回key1与key2 中相差的成员, 而且与key的顺序有关,即返回差集
⑤ 集合的交集运算A∩B :sinter key1 key2 ...
⑥ 集合的井集运算A∪B:sunion key1 key2 ...
⑦ 其他命令

scard key		--  获取set中成员的数量
srandmember key		--  随机返回set中的一个成员
sdiffstore destination key1 key2 ……		--  将key1、key2相差的成员存储在destination上
sinterstore destination key1 key2 ……		--  将返回的交集存储在destination上
sunionstore destination key1 key2 ……		--  将返回的并集存储在destination上

6、存储sortedset
Sorted-Set 和Set 类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中。它们之间的主要差别是Sorted-Set 中的每一个成员都会有一个分数(score)与之关联,Redis 正是通过分数来为集合中的成员进行从小到大的排序。然而需要额外指出的是,尽管Sorted-Set 中的成员必须是唯一的, 但是分数(score)却是可以重复的。
在Sorted-Set 中添加、删除或更新一个成员都是非常快速的操作, 其时间复杂度为集合中成员数量的对数。由于Sorted-Set 中的成员在集合中的位置是有序的, 因此,即便是访问位于集合中部的成员也仍然是非常高效的。事实上,Redis 所具有的这一特征在很多其它类型的数据库中是很难实现的。应用实例例如: 游戏排名、微博热点话题等使用场景。
① 添加元素:zadd key score member score2 member2 …
将所有成员以及该成员的分数存放到sorted-set 中,如果该元素已经存在则会用新的分数替换原有的分数,返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
② 获得元素
zscore key member : 返回指定成员的分数
zcard key : 获取集合中的成员数量
③ 删除元素:zrem key member[member ... ]
④ 范围查询
zrange key start end [withscores] : 获取集合中脚标为start-end的成员,[withscores]参数表明返回的成员包含其分数。
zrevrange key start stop [withscores] : 照元素分数从大到小的顺序返回索引从start 到stop之间的所有元素(包含两端的元素)
zremrangebyrank key start stop: 按照排名范围删除元索
zremrangebyscore key min max : 按照分数范围删除元素
⑤ 其他命令

zrangebyscore key min max [withscores] [limit offset count]		-- 返回分数在[min,max]的成员并按照分数从低到高排序。[withscores]:显示分数;[limit offset count]:表明从脚标为offset的元索开始并返回count个成员。
zincrby key increment member		-- 设宣指定成员的增加的分数,返回值是更改后的分数
zcount key min max		-- 获取分数在[min,max]之间的成员
zrank key member		-- 返回成员在集合中的排名(从小到大)
zrevrank key member		-- 返回成员在集合中的排名(从大到小)

7、keys 的通用操作
keys pattern : 获取所有与pattern匹配的key,返回所有与该key匹配的keys。表示任意一个或多个字符, 表示任意一个字符
示例:

keys *		-- 所有key
keys my?		-- 以my开头的key

del key1 key2 ...: 删除指定的key
exists key : 判断该key 是否存在, 1 代表存在, 0 代表不存在
rename key newkey : 为当前的key重命名
⑤ .expire key time:设置过期时间,时间单位为秒
示例:expire company 1000
ttl key : 获取该key所剩的是超时时间, 如果没有设置超时返回-1,如果返回-2表示超时不存在。
type key : 获取指定key的类型,该命令将以字符串的格式返回,返回的字符串为string、list、set、hash 和zset类型,如果key不存在返回none。

六、Redis特性

1、多数据库
一个Redis实例可以包括多个数据库, 客户端可以指定连接某个redis实例的哪个数据库, 就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库。
一个redis 实例最多可提供16个数据库,下标从0 到15,客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库,如连接1 号库:select 1

2、将当前库的key 移植到1号库中:move newkey 1

3、服务器命令
ping:测试连接是否存活
select [0~15]:选择数据库
quit:退出连接。
dbsize:返回当前数据库中key的数目
info :获取服务器的信息和统计
flushdb:删除当前选择数据库中的所有key
flushall:删除所有数据库中的所有key

4、消息订阅与发布
subscribe channel:订阅频道, 例: subscribe mychat ,订阅mychat 这个频道
psubscribe channel*:批量订阅频道, 例: psubscribe s*,订阅以s开头的频道
publish channel content:在指定的频道中发布消息, 如publish mychat ’today is a newday’

5、Redis事务
和众多其它数据库一样,Redis作为NoSQL 数据库也同样提供了事务机制。在Redis 中,MULTI/EXEC/DISCARD这三个命令是我们实现事务的基石。
在事务中的所有命令都将会被串行化的顺序执行, 事务执行期间, Redis 不会再为其它客户端的请求提供任何服务,从而保证了事物中的所有命令被原子的执行。
和关系型数据库中的事务相比, 在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。

multi : 开启事务用于标记事务的开始, 其后执行的命令部将被存入命令队列, 直到执行EXEC时,这些命令才会被原子的执行, 类似与关系型数据库中的 begin transaction
exec : 提交事务,类似与关系型数据库中的: commit
discard : 事务回滚, 类似与关系型数据库中的: rollback

七、Jedis入门

1、Jedis介绍
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java 、C、C#、C++、php、Node.js、Go等。
在官方网站里列一些Java 的客户端,有Jedis、Redisson 、Jredis、JDBC-Redis等其中官方推荐使用Jedis和Redisson。在企业中用的最多的就是Jedis,下而我们就重点学习下Jedis 。

2、Java连接Redis
① 导包:commoms-pool2-2.3.jarjedis-2.7.0.jar
② 单实例连接

public class JedisDemo {
	public static void main(String[] args) {
		//获取Jedis对象
		Jedis jedis=new Jedis("192.168.134.131", 6379);
		//操作redis数据库
//		jedis.set("iphone", "19999999999");
//		
//		String iphone = jedis.get("iphone");
//		System.out.println(iphone);
		
		jedis.hset("myhashjava", "username", "zhangsan");
		jedis.hset("myhashjava", "age", "19");
		String age = jedis.hget("myhashjava", "age");
		System.out.println(age);
		//使用jedis 必须关闭
		jedis.close();
	}
}

③ 连接池连接

public class PoolDemo{
	public static void main(String[] args) {
		//获取jedis池的配置对象
		JedisPoolConfig jc=new JedisPoolConfig();
		//配置最大连接数
		jc.setMaxTotal(20);
		//配置等待超时时间
		jc.setMaxWaitMillis(8000);
		
		//创建jedis池
		JedisPool pool=new JedisPool(jc, "192.168.134.131", 6379);
		//获取jedis对象
		Jedis jedis = pool.getResource();
		jedis.set("name", "xiaoming");
		
		String name = jedis.get("name");
		System.out.println(name);
		
		//关闭jedis
		jedis.close();
	}
}

④ 用配置文件连接池连接
jedis.properties

maxTotal=20
maxWaitMillis=7000
host=192.168.134.131
port=6379
public class JedisPoolUtils {
	private static JedisPoolConfig jc = null;
	private static int maxTotal = 0;
	private static long maxWaitMillis = 0;
	private static String host = null;
	private static int port=0;
	private static JedisPool pool=null;
	static{
		jc=new JedisPoolConfig();
		//获取properties中的配置数据
		ResourceBundle re = ResourceBundle.getBundle("jedis");
		maxTotal=Integer.parseInt(re.getString("maxTotal"));
		maxWaitMillis=Long.parseLong(re.getString("maxWaitMillis"));
		
		jc.setMaxTotal(maxTotal);
		jc.setMaxWaitMillis(maxWaitMillis);
		host = re.getString("host");
		port = Integer.parseInt(re.getString("port"));
		//创建Jedis池
	     pool=new JedisPool(jc, host, port);
	}
	
	public static Jedis getJedis(){
		return pool.getResource();	
	}
}
public class TestUtils {
	public static void main(String[] args) {
		//获取池中jedis
		Jedis jedis=JedisPoolUtils.getJedis();
		jedis.set("username2", "xiaowang");	
		jedis.close();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值