1 NoSql介绍
????????2007年10月30日,北京奥运会门票面向境内公众第二阶段预售正式启动。上午一开始,公众提交申请空前踊跃。上午9时至10时,官方票务网站的浏览量达到了800万次,票务呼叫中心热线从9时至10时的呼入量超过了380万人次。由于瞬间访问数量过大,技术系统应对不畅,造成很多申购者无法及时提交申请,为此北京奥组委票务中心对广大公众未能及时、便捷地实现奥运门票预订表示歉意。 ????????奥运会门票预售系统开放第一天,上午9点正式开始售票到中午12点,3个小时内,票务网站被浏览次数达到2000万次。 ????????12306:一个在奔溃中的网站。 ????????原因:海量用户和高并发。 ????????性能瓶颈:瓷片IO性能低下。 ????????扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群。 ????????解决思路:降低磁盘IO次数–内存存储;去除数据间关系,仅存储数据。 ????????NoSQL:即 Not-Only SQL( 泛指非关系型的数据库),作为关系型数据库的补充。 ????????Nosql 作用:应对基于海量用户和海量数据前提下的数据处理问题。 常见 Nosql 数据库: Redis 、 memcache 、HBase 、 MongoDB。
2 Redis简介
????????Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库 ????????特征:
- 数据间没有必然的关联关系
- 内部采用单线程机制进行工作
- 高性能:
官方提供测试数据,50个并发执行100000 个请求,读的速度是110000 次/s,写的速度是81000次/s。 - 多数据类型支持:
(1)字符串类型 string (2)列表类型 list (3)散列类型 hash (4)集合类型 set (5)有序集合类型 sorted_set - 持久化支持:
可以进行数据灾难恢复
3 Redis下载安装及基本使用
- Redis下载解压
- Redis启动
执行redis-server.exe: - 客户端连接
执行redis-cli.exe:
- 基本操作
信息添加:set key value 信息查询:get key,如果不存在,返回空(nil)
4 Redis数据类型
????????redis是一个Map,其中所有的数据都是采用key:value的形式存储。数据类型指的是存储的数据的类型,也就是value部分的类型,key部分永远都是字符串。String在Redis内部存储默认就是一个字符串,当遇到增减类操作incr、decr时会转成数值型进行操作。redis所有的操作都是原子性的,采用单线程处理所有任务,命令是一个一个执行的,因此无需考虑并发带来的影响。
4.1 String类型
????????通常存储字符串,如果字符串以整数的形式展示,可以作为数字操作使用。
- 添加/修改数据: set key value
- 获取数据: get key
- 删除数据: del key
- 添加/修改多个数据:mset key1 value1 key2 value2…
- 获取多个数据:mget key1 key2…
- 追加信息(存在追加,否则新建):append key value
- 数值数据增加1:incr key
- 数据数据增加指定的值:incrby key increment
- 数值数据增加指定的小数:incrbyfloat key increment
- 数值数据减少1:decr key
- 数值数据减少指定的值:decrby increment
- 按秒设置数据的时效性:setex key seconds value
- 按毫秒设置数据的时效性:psetex key milliseconds value
4.2 Hash类型
????????对一系列存储的数据进行编组,典型应用存储对象信息,一个存储空间保存多个键值对数据,Hash类型:底层使用哈希表结构实现数据存储。Hash结构优化:如果field数亮较少,存储结构优化为数组结构,如果field数量较多,存储结构优化为HashMap结构。
- 添加/修改数据:hset key field value
- 获取数据:hget key field
- 获取所有field:hgetall key
- 删除数据:hdel key field1 field2…
- 添加/修改多个数据:hmset key field1 value1 field2 value2…
- 获取多个数据:hmget key field1 field2
- 获取哈希表中字段的数量:hlen key
- 获取哈希表中是否存在指定的字段:hexists key field
- 获取哈希表中所有字段名或字段值:hkeys key/hvals key
- 设定指定字段的数值数据增加指定的值:hincrby key field increment / hincrbyfloat key float increment
????????注意事项: ????????(1)Hash类型下的value只能存储String,不允许存储其他数据类型,不存在嵌套现象,如果数据未获取到,对应的值为nil。 ????????(2)每个hash可以存储2的32次方-1个键值对。 ????????(3)hgetall操作可以获取全部属性,,如果内部field过多,遍历整体数据集效率会很低,有可能会成为数据访问的瓶颈。
4.3 List类型
????????保存多个数据,底层使用双向列表存储结构实现。
- 添加/修改数据:lpush/rpush key value1 value2…
- 获取数据:
lrange key startIndex stopIndex lindex key index llen key - 获取并移除数据:lpop/rpop key
- 规定时间内获取并移除数据(list阻塞数据获取):
blpop/brpop key1 [key2] timeout brpoplpush source destination timeout - 移除指定数据:lrem key count value
从左删除count个value
????????List中的数据都是String类型,数据总量是优先的,最多2的32次方-1个元素。 ????????List具有所有的概念,但是操作数据时通常以队列的形式进行入队和出队操作,或者以栈的形式进行入栈和出栈的操作。 ????????获取全部数据操作结束索引为-1。 ????????List可以对数据进行分页操作,通常第一页的信息来自原list,第2页及更多的信息通过数据加载。
4.4 Set类型
????????能够存储大量数据,在查询方面提供更高的效率,存储结构与Hash结构完全相同,仅存储键,不存储值(nil),并且键是不允许重复的。
- 添加数据:sadd key member1 membe2…
- 获取全部数据:smembers key
- 删除数据:srem key member1 member2…
- 获取集合数据总量:scard key
- 判断集合中是否包含指定数据:sismember key member
- 随机获取集合中指定数量的数据:srandmember key [count]
- 随机获取集合中指定数量的数据并将数据移出集合:spop key [count]
????????Set还可以进行交、并、差的操作,红色部分为交、并、差操作的结果集。
- 求两个集合的交、并、差
sinter key1 [key2] sunion key1 [key2] sdiff key1 [key2] - 求两个集合的交、并、差并存储到指定集合中
sinterstore destination key1 [key2] sunionstore destionation key1 [key2] sdiffstore destination key1 [key2] - 将指定数据从原始集合中移动到目标集合中
smove source destination member
4.5 sorted_set类型
????????可以保存排序的数据,根据自身的特征进行排序,在Set的基础上增加可排序字段。
- 添加数据:zadd key score1 member1 [score2 member2]
- 获取全部数据:
zrange key start stop [withscores] zreverange key start stop [withscores] - 删除数据:zrem key member [member…]
- 按条件获取数据
zrangebyscore key min max [withscores] [limit offset count] zreverangebyscore key min max - 条件删除数据
zremrange key start stop zremrangebyscore key min max 注意:min和max用于限定排序的条件,start和stop用于限定索引,offset和count用于限定开始位置和查询数量 - 获取集合数据总量:scard key / scount key min max
同时也支持交并操作,这里不再赘述。
5 Redis通用指令
- 删除指定key:del key
- 判断key是否存在:exists key
- 获取key的类型:type key
- 为key设定有效期:
expire key sceonds pexpire key milliseconds - 获取key有效时间:ttl/pttl key
- 按通配符查询key:keys pattern
- 为key改名:rename/renamenx key newkey
- 对所有key排序:sort
- 切换数据库:select index
redis为每个服务提供16个数据库,编号从0.-15,每个数据库之间的数据相互独立。 - 数据移动:move key db
- 数据清除(慎用):flushdb、flushall
6 Jedis
Java语言连接Redis服务
6.1 Jedis的hello jedis程序
(1)首先引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
(2)编写测试方法
@Test
public void testJedis(){
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.set("begin","hello jedis");
String name = jedis.get("begin");
System.out.println(name);
jedis.close();
}
(3)打印结果
6.2 Jedis测试List
(1)编写测试方法
@Test
public void testList(){
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.lpush("nums","1","2","3");
jedis.rpush("nums","0");
List<String> list1 = jedis.lrange("nums", 0, -1);
for(String s : list1){
System.out.print(s+ " ");
}
System.out.println();
System.out.println(jedis.llen("nums"));
jedis.close();
}
(2)打印结果
6.3 Jedis测试Hash
(1)编写测试方法
@Test
public void testHash(){
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.hset("student","s1","梁朝伟");
jedis.hset("student","s2","刘德华");
jedis.hset("student","s3","张国荣");
Map<String, String> hash = jedis.hgetAll("student");
System.out.println(hash);
System.out.println(jedis.hlen("student"));
jedis.close();
}
(2)打印结果
7 Redis持久化
????????什么是持久化? ????????持久化就是利用永久性存储介质对数据进行保存,可以用来进行数据恢复,持久化可以防止数据的丢失,确保数据安全性。 ????????Redis两种持久化方案: ????????(1)RDB:数据(快照) ????????将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据。 ????????(2)AOF::过程(日志) ????????将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程。
7.1 RDB
命令执行: 执行命令者:用户(Redis操作者) 执行时间:及时(随时) 执行事件:保存数据
7.1.1 save方式
????????手动执行一次保存操作,注意:因为是单线程执行序列,save指令的执行会阻塞当前redis服务器,知道当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用。
7.1.2 bgsave方式
????????由客户端发起指令,Redis服务器控制指令在合理的时间保存数据,在后台执行。bgsave指令是对save阻塞问题做的优化,Redis内部所有涉及RDB操作都采用bgsave的方式,save可以直接放弃使用。
7.1.3 save second changes方式
????????满足限定时间内key的变换数量达到指定数量即进行持久化。second:监控时间范围;changes:监控key的变化量。在conf文件中进行配置。实际执行的还是bgsave操作。
7.1.4 save和bgsave异同
7.1.5 RDB优点
- RDB是一个紧凑压缩的二进制文件,存储效率高
- RDB内部存储的Rdis在某个时间点的快照,非常适用于数据备份,全量复制等场景
- RDB数据恢复的速度要比AOF快很多
- 应用:服务器中没X小时执行bgsave,并将RDB文件拷贝到远程服务器中,用于灾难恢复
7.1.6 RDB缺点
- RDB无论是执行指令还是利用配置,无法做到实时持久化,具有较大可能性会丢失数据
- bgsave每次运行都要执行fork操作创建子进程,要牺牲掉一些性能
- Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间的数据格式无法兼容现象。
7.2 AOF
????????AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的,记录数据产生的过程。AOF的主要作用是解决了持久化的实时性,目前已经是Redis持久化的主流方式。
7.2.1 AOF写数据的三种策略
- always(每次)
每次写操作都同步到AOF文件中,数据零误差,性能较低,不建议使用。 - everysec(每秒)
每秒将缓冲区的指令同步到AOF文件中,,数据准确性较高,性能较高,建议使用,也是默认配置在系统突然宕机的情况下丢失1秒的数据。 - no(系统控制)
由系统控制每次同步到AOF文件的周期,整体过程不可控
7.2.2 AOF重写
????????重写是将对同一个数据的若干个命令结果转换为最终结果数据对应的指令进行记录。可以降低磁盘占用量,提高持久化效率和数据恢复效率。
7.2.3 RDB与AOF异同
|