###前言redis
昨天和室友去包夜,玩了一夜的
LOL
,跪了一整夜,可是很开心。从S1
末开始玩LOL
的我,到如今仍是青铜,真是菜的抠脚。最近负能力满满的,惟有睡觉和学习才可解忧愁。今天也看了慕课网上面的《Redis
入门》,来记一下学习笔记。(写这篇文章开头的时候应该是一个星期以前)算法
###NoSQL概述shell
NoSQL
就是Not Only SQL
的意思,是非关系型数据库。数据库
为何须要NoSQL
?vim
High performance
- 高并发读写数组
Huge Storage
- 海量数据的高效率存储和访问缓存
High Scalability & High Availability
- 高可扩展性和高可用性安全
NoSQL数据库的四大分类bash
键值(Key - Value
)存储:优势是快速查询,缺点存储的数据缺乏结构化。服务器
列存储:优势是查询比较快,扩展性比较强,缺点是功能相对局限。
文档数据库:对应的产品就是MongoDB
。对数据结构要求不是特别严格,查询性能不能特别高,缺乏统一查询的语法。
图形数据库:优势是利用图结构相关的算法,缺点是须要对整个图进行结算才能得出结果,不能做为分布式的解决方案。
NoSQL
的特色,美滋滋。
###Redis的概述
高性能键值对数据库,支持的键值数据类型:
字符串类型 - String
列表类型 - Set
有序集合类型 - Sorted Set
散列类型 - Hash
集合类型 - List
Redis
的应用场景
缓存
任务队列
网站访问统计
应用排行榜
分布式集群架构中的session分离
###Redis在Linux上的使用 能够看我这篇文章【Linux学习】 Redis经常使用的一些指令
###Jedis的入门
Java
平台上使用redis
,确定须要Jedis
这个客户端。首先在pom
文件中引入Jedis
的依赖<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
复制代码
public void methodOne() {
Jedis jedis = new Jedis("100.64.84.47", 6379);
jedis.set("name", "cmazxiaoma");
String value = jedis.get("name");
System.out.println(value);
jedis.close();
}
复制代码
public void methodTwo() {
//得到链接池的配置对象
JedisPoolConfig config = new JedisPoolConfig();
//设置最大链接数
config.setMaxTotal(30);
//设置最大空闲链接数
config.setMaxIdle(10);
//得到链接池
JedisPool jedisPool = new JedisPool(config, "100.64.84.47", 6379);
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String value = jedis.get("name");
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
jedisPool.close();
}
}
}
复制代码
public class JedisDemo1Test {
private JedisDemo1 demo;
@Before
public void setUp() {
demo = new JedisDemo1();
}
@Test
public void methodOne() throws Exception {
demo.methodOne();
}
@Test
public void methodTwo() throws Exception {
demo.methodTwo();
}
}
复制代码
运行Test Case
,测试成功。
咱们在Xshell
软件,输入get name
指令,也能够看到输出cmazxiaoma
。
###Redis的数据结构
####String
Key
定义的注意点:
存储String
:
Value
最多能够容纳的数据长度是512M
。存储String
经常使用的命令:
赋值
取值
删除
数值增减
若是属性不存在的话,那么integer
类型默认为0
。
若是name
属性的值不能转换成integer
类型,那么会抛出ERR is not an integer or out of range
异常。
decr
指令也是同样的。
incrby
、decrby
也是同样的,很简单。
append
指令能够拼接字符串。
若是append key cmazxiaoma
。这个key
不存在的话,首先会建立这个key
,而后存入cmazxiaoma
内容,接着输出cmazxiaoma
。
####Hash
赋值,可使用hset myhash key value
单一赋值、hmset myhash key value key value
屡次赋值。
取值,能够用hget myhash key
单一取值、hmget myhash key key
多个取值、hgetall
取出全部key
所对应的值。
删除 ,能够用hdel myhash key
删除单一的key
。
hdel myhash key key
删除多个的key
。
del myhash
删除myhash
中全部的key
。
数值增减,hincrby myhash key 100
使用hexists myhash key
判断key
是否在myhash
中存在,存在返回1
,不存在返回0
。
hlen myhash
获取myhash
中存在key
的数量。
hkeys myhash
获取myhash
中全部的key
。
hvals myhash
获取myhash
中全部的values
。
####List
存储list:
ArrayList
使用数组方式LinkedList
使用双向链表方式两端添加
lpush a b c
命令在左端添加,那么c
确定是在最左端。
rpush a b c
命令在右端添加,那么c
确定是在最右端。
两端弹出
lpop mylist
弹出mylist
中头部元素、rpop mylist2
弹出mylist2
尾部中的元素。它们都是3
。
mylist
、mylist2
。
查看列表
lrange mylist 0 5
来查看mylist
列表,mylist
插入的方式从头结点开始添加的,那么输出确定是321abc
。
lrange mylist2 0 5
查看mylist2
列表,mylist2
插入的方式是从最右端添加的,那么输出确定是abc123
获取列表元素的个数
llen mylist
命令
扩展命令
使用lpushx mylist x
,使插入的元素在头部位置。
使用rpushx mylist x
,使插入的元素在尾部位置。
使用lrem mylist count element
,count
表明是删除的次数,element
表明是须要删除的元素。若是count > 0
表明删除的方式从头至尾,删除count
个element
,count < 0
表明删除的方式从尾到头,删除count
个element
。若是count = 0
,删除mylist
中全部和element
相同的元素。
lrem mylist 2 test1
lrem mylist -2 test1
lrem mylist 0 cmazxiaoma
在某一个下标位置插入元素。lset mylist index element
在目标元素以前插入指定的元素。linsert mylist before helloworl before_helloworld
在目标元素以后插入指定的元素。linsert mylist helloworld after after_helloworld
弹出mylist
中最后一个元素,并插入到mylist
中的头部。rpoplpush mylist mylist
rpoplpush
使用场景
####Set 和List
类型不一样的是,Set
集合中不容许出现重复的元素。
添加/删除元素
sadd myset a b c
,若是咱们重复添加相同的元素,确定是不成功的。好比sadd myset a
。
srem myset a
,删除myset
中的a
元素。
myset
中的元素。smembers myset
myset
中的成员。sismember myset a
,返回0
表明不存在,返回1
表明存在。
得到集合中的元素, smembers myset
集合中的差集运算,sdiff myset2 myset
。myset2
中元素有b,c,d
。myset
中元素有b,c
。它们之间的差集运算结果应该为d
。
集合中的交集运算,sinter myset2 myset
,应该输出cb
。
集合中的并集运算,sunion myset2 myse
t,应该输出cbd
。
扩展命令
scard myset
查看myset
有多少个元素。
srandmember myset
随机返回myset
中的一个元素。
sdiffstore new_myset myset2 myset
把myset
和myset2
差集元素的结果存储到new_myset
中。(sinterstore
, sunionstore
也是同样的用法)
Set使用场景
####SortedSet SortedSet
中的成员在集合中的位置是有序的。
添加元素 zadd mysort 70 cmazxiaoma 80 xiaoma 100 doudou
得到元素
zcard mysort
得到mysort
中全部元素的个数
得到mysort
中name
为cmazxiaoma
对应的成绩。zscore mysort cmazxiaoma
删除元素,zrem mysort cmazxiaoma deli doudou xiaoma
范围查询 zrange mysort 0 -1
,输出的key
是按成绩正序排列。
若是输出的数据项要带上成绩的话,指令应该是zrange mysort 0 -1 withscores
若是输出的数据项想按成绩逆序排序,那么就应该zrevrange mysort 0 -1 withscores
若是想按排名范围进行删除的话,那么应该zremrangebyrank mysort 0 2
若是想按成绩范围进行删除的话,那么应该zremrangebyscore mysort 0 10
。顾名思义删除成绩在0-10
以内的数据项。
扩展命令
查看分数在0-10
以内的学生信息,zrangebyscore mysort 0 10 withscores
查看分数在0-100
以内且在第1
行-第2
行的学生信息。zrangebyscore mysort 0 100 withiscores limit 0 2
给cmazxiaoma
的成绩加100
分。zincrby mysort cmazxiaoma 100
查当作绩0-10
之间的学生的个数。zcount mysort 0 10
Sorted Set
使用场景
如大型在线游戏积分排行榜
构建索引数据
###Redis中的通用命令
key *
获取全部redis中的key
keys my*
获取全部redis
中以my
开头的key
exists mylist
查看redis
中是否存在mylis
t,0
表明不存在,1
表明存在。
rename name new_name
给名字为name
的数据结构重命名为new_name
expire new_name 10
设置redis
中new_name
过时时间,经过ttl new_name
看到其距离过时的时间。
type mylist
,能够查看mylist
对应的数据结构类型。
###Redis的事务
Redis
相关的特性:
多数据库
Redis
事务
一个Redis
最多能够提供16
个数据库,下标分别是0-15
。客户端默认链接的是第0
号数据。咱们能够经过select index
来选择数据库。
咱们想把第0
号的数据库中某些key
移动到第1
号数据库里面,那么咱们该怎么作呢。经过move cmazxiaoma_test_mayday_5 1
就能够完成。
咱们能够经过multi
、exec
、discard
来完成事务操做。事务执行期间,Redis
不会为其余客户端提供任何服务,以保证事务中的全部命令原子执行。multi
至关于开启事务,exec
至关于提交,discard
至关于回滚。
首先咱们在第一个客户端进行以下操做。咱们在第一个客户端开启了事务,在事务中咱们incr num
2
次,按理来讲,get num
应该等于4
。
咱们在第二个客户端输入get num
,发现num
仍是2
。那么证实了咱们的结论:事务执行期间,Redis
不会为其余客户端提供任何服务,以保证事务中的全部命令原子执行。
若是咱们在第一个客户端提交了事务。
接着咱们在第二个客户端get num
,发现能够num
的值获得了更新。
咱们能够演示一下回滚操做,首先set user cmazxiaoma
,接着开启事务,在事务中set user xiaoma
,而后进行回滚操做,发现 get user
依然是cmazxiaoma
。
###Redis的持久化 Redis
的性能体如今它把数据都保存在内存当中。咱们把内存中的数据同步到硬盘当中的操做称之为持久化。
Redis
持久化方式:
RDB
方式,在指定的时间内,把内存中的数据快照写入到硬盘当中。
AOF
方式,将以日志的形式记录服务器所处理的每个操做。当Redis
服务器启动之初,它会读取该aof
文件,会从新构建咱们的数据库。保证咱们启动以后,保证数据的完整性。
无持久化,咱们能够经过配置禁止Redis
服务器的持久化,咱们认为Redis
就是缓存的一种机制了。
同时使用。
RDB
:
默认状况下,每隔一段时间redis
服务器程序会自动对数据库作一次遍历,把内存快照写在一个叫作"dump.rdb"
的文件里,这个持久化机制叫作SNAPSHOT
。有了SNAPSHOT
后,若是服务器宕机,从新启动redis
服务器时,redis
会自动加载"dump.rdb"
,将数据库状态恢复上一次SNAPSHOT
的状态。
Redis
服务器初始化过程当中,设定了定时时间,每隔一段时间就会触发持久化操做,进入定时事件处理程序中,就会fork
出子进程来进行持久化操做。
Redis
服务器预设了save
指令,客户端可要求服务器进程中断服务,执行持久化操做。
咱们能够经过vim /etc/redis.conf
打开配置文件,能够看到如下配置。
同时咱们还能够看到内存快照输出在file
文件名。
优缺点:
若是数据集很大,RDB
相对于AOF
启动效率很更高。
若是想保证数据的高可用性,最大限度的避免数据的丢失,RDB
将不是一个好的选择。由于系统在定时持久化操做以前,还没来得及在硬盘写入数据就发生宕机的话,就形成了数据的丢失。
RDB
经过fork
出子线程来完成数据持久化操做,若是当数据集很大的时候,可能会致使服务器中止几百ms
,或者几s
。
AOF
(append only file
):
对于Redis
服务器而言,其缺省的机制是RDB
,若是须要使用AOF
,则须要修改appendonly no
改为appendonly yes
。Redis
在每一次收到数据修改的命令以后,都会将其追加到AOF
文件中。在Redis
下一次从新启动时,须要加载AOF
文件中的信息来构建最新的数据到内存中。
能够记录服务器的全部写操做。在服务器从新启动时,会把全部的写操做从新执行一遍从而实现数据的备份。当写操做集过大(比原有的数据集还大),Redis
会重写写操做集。
带来更好的数据安全性,有3
种同步策略,每秒同步,每修改同步,不一样步。 每秒同步也是异步完成的,效率也很是高。缺点是一旦系统发生宕机的现象,那么这一秒中的修改的数据就会发生丢失。每修改同步,咱们能够视为同步持久化。每一次发生数据的变化,就会当即的记录在磁盘,这种效率很低,可是很安全。
采用append
追加的模式,就算系统发生宕机,也不会影响咱们日志文件中已经存在的内容。然而咱们本次操做中,只写入了一半数据就出现了系统崩溃的问题。在Redis下一次启动以前,咱们能够经过"redis-check-aof --fix <filename>"
命令来修复坏损的AOF
文件,解决数据一致性的问题。
对于相同数量的数据集而言,AOF
文件一般要大于RDB
文件。
AOF
在运行效率上每每会慢于RDB
。
RDB
和AOF
的区别 前者是保存了数据自己,然后者是记录了数据的变动。###尾言
这篇文章最后在网吧完成的,勿以善小而不为。