1、NoSQL数据库简介
2、Redis的介绍及安装启动
3、Redis的五大数据类型
4、Redis的Java客户端Jedis
5、Redis的事务
6、Redis的持久化
7、Redis的主从复制
8、Redis的集群
Redis介绍
Redis是一个开源的key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是**Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步**。
Redis应用场景
1、配合关系型数据库做高速缓存
- 高频次,热门访问的数据,降低数据库IO
- 分布式架构,做session共享
2、由于其拥有持久化能力,利用其多样的数据结构存储特定的数据。
3、Redis从哪获得
- Redis官方网站 http://Redis.io
- Redis中文官方网站 http://www.Redis.net.cn/
Redis安装
安装步骤:(3.2.5 for Linux)
- 下载获得redis-3.2.5.tar.gz后将它放入我们的Linux目录/opt
- 解压命令:tar -zxvf redis-3.2.5.tar.gz
- 解压完成后进入目录:cd redis-3.2.5
- 在redis-3.2.5目录下执行make命令
在redis-3.2.5目录下再次执行make命令
![](https://cdn.nlark.com/yuque/0/2020/png/2397310/1597967540186-e2163447-c375-40af-873f-8a1030e24fec.png#crop=0&crop=0&crop=1&crop=1&height=57&id=bpqrd&originHeight=80&originWidth=557&originalType=binary&ratio=1&rotation=0&showTitle=false&size=0&status=done&style=none&title=&width=397)![image.gif](https://cdn.nlark.com/yuque/0/2020/gif/2397310/1597967543687-be9f53cb-df90-4ceb-bfdf-cecdc2573353.gif#crop=0&crop=0&crop=1&crop=1&height=1&id=DKQX5&name=image.gif&originHeight=1&originWidth=1&originalType=binary&ratio=1&rotation=0&showTitle=false&size=43&status=done&style=none&title=&width=1)<br /> 6.在redis-3.2.5目录下再次执行make命令<br /> 7.执行完make后,跳过Redis test 继续执行make install<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/2397310/1597967540083-7dd7aa64-72b1-4dc9-a612-62d29d6b6dce.png#crop=0&crop=0&crop=1&crop=1&height=182&id=tXfzo&originHeight=326&originWidth=684&originalType=binary&ratio=1&rotation=0&showTitle=false&size=0&status=done&style=none&title=&width=382)![image.gif](https://cdn.nlark.com/yuque/0/2020/gif/2397310/1597967543708-0c05ea4f-667c-4980-874f-3d617fe9f272.gif#crop=0&crop=0&crop=1&crop=1&height=1&id=x6DY5&name=image.gif&originHeight=1&originWidth=1&originalType=binary&ratio=1&rotation=0&showTitle=false&size=43&status=done&style=none&title=&width=1)
Redis目录
- Redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何(服务启动起来后执行)
- Redis-check-aof:修复有问题的AOF文件,rdb和aof后面讲
- Redis-check-dump:修复有问题的dump.rdb文件
- Redis-sentinel:Redis集群使用
- redis-server:Redis服务器启动命令
- redis-cli:客户端,操作入口
Redis启动
- 1、备份redis.conf:拷贝一份redis.conf到其他目录
- 2、修改redis.conf文件将里面的daemonize no 改成 yes,让服务在后台启动
3、启动命令:执行 redis-server /root/myredis/redis.conf
4 . 4、用客户端访问: redis-cli 多个端口可以 redis-cli –p 6379
5. 5、测试验证: ping
Redis关闭
单实例关闭:redis-cli shutdown
也可以进入终端后再关闭
多实例关闭,指定端口关闭:redis-cli -p 6379 shutdown
Redis相关知识
1、端口6379从何而来
2、默认16个数据库,类似数组下标从0开始,初始默认使用0号库
使用命令 select
3、统一密码管理,所有库都是同样密码,要么都OK要么一个也连接不上。
Redis相关知识—单线程
Redis是单线程+多路IO复用技术
多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。 串行 vs 多线程+锁(memcached) vs 单线程+多路IO复用(Redis)
Redis 五大数据类型 —Key
- keys * 查询当前库的所有键
- exists
判断某个键是否存在 - type
查看键的类型 - del
删除某个键 - expire
为键值设置过期时间,单位秒。 - ttl
查看还有多少秒过期,-1表示永不过期,-2表示已过期 - dbsize 查看当前数据库的key的数量
- flushdb 清空当前库
- flushall 通杀全部库
String
- String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。
- String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
- String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M(一般不建议装满)
- get
查询对应键值 - set
添加键值对 - append
将给定的 追加到原值的末尾 - strlen
获得值的长度 - setnx
只有在 key 不存在时设置 key 的值 - incr
A、将 key 中储存的数字值增1。B、只能对数字值操作,如果为空,新增值为1 - decr
A、将 key 中储存的数字值减1。B、只能对数字值操作,如果为空,新增值为-1 - incrby / decrby
<步长> 将 key 中储存的数字值增减。自定义步长。
原子性
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
- (1) 在单线程中, 能够在单条指令中完成的操作都可以认为是” 原子操作”,因为中断只能发生于指令之间。
- (2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis单命令的原子性主要得益于Redis的单线程
- mset
….. 同时设置一个或多个 key-value对 - mget
….. 同时获取一个或多个 value - msetnx
….. 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。 - getrange
<起始位置> <结束位置> 获得值的范围,类似java中的substring - setrange
<起始位置> 用 覆写 所储存的字符串值,从<起始位置>开始。 - setex
<过期时间> 设置键值的同时,设置过期时间,单位秒。 - getset
以新换旧,设置了新值同时获得旧值。
List
- 单键多值
- Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
- 它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
- lpush/rpush
…. 从左边/右边插入一个或多个值。 - lpop/rpop
A、从左边/右边吐出一个值。 B、值在键在,值亡键亡。 - rpoplpush
从 列表右边吐出一个值,插到 列表左边。 - lrange
按照索引下标获得元素(从左到右) - lindex
按照索引下标获得元素(从左到右) - 获得列表长度 l len
- linsert
before 在 的前面插入 - lrem
从左边删除n个value(从左到右)
set
set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的(可以自动去重),当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的复杂度都是O(1)。
- sadd
….. 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。 - smembers
取出该集合的所有值。 - sismember
判断集合 是否为含有该 值,有返回1,没有返回0 - scard
返回该集合的元素个数。 - srem
…. 删除集合中的某个元素。 - spop
随机从该集合中吐出一个值。 - srandmember
A、随机从该集合中取出n个值。 B、不会从集合中删除 - sinter
返回两个集合的交集元素。 - sunion
返回两个集合的并集元素。 - sdiff
返回两个集合的差集元素。
hash
- Redis hash 是一个键值对集合。
- Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
- 类似Java里面的Map
- hset
给 集合中的 键赋值 - hget
从 集合 取出 value - hmset
… 批量设置hash的值 - hexists key
查看哈希表 key 中,给定域 field 是否存在。 - hkeys
列出该hash集合的所有field - hvals
列出该hash集合的所有value - hincrby
为哈希表 key 中的域 field 的值加上增量 increment - hsetnx
将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在 .
zset (sorted set)
Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的所有成员都关联了一个评分(score) ,这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
- zadd
… - 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
- zrange
[WITHSCORES] - A、返回有序集 key 中,下标在
之间的元素 。 B、带WITHSCORES,可以让分数一起和值返回到结果集。 - zrangebyscore key min max [withscores] [limit offset count]
- 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于min 或max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
- zrevrangebyscore key max min [withscores] [limit offset count] 同上,改为从大到小排列。
- zincrby
为元素的score加上增量 - zrem
删除该集合下,指定值的元素 - zcount
统计该集合,分数区间内的元素个数 - zrank
返回该值在集合中的排名,从0开始。
Java的Redis客户端Jedis
通过操作java代码来操作redis,所以提供了jedis这个工具
Jedis所需要的jar包 : Commons-pool-1.6.jar Jedis-2.1.0.jar
用windows中的Eclipse连接虚拟机的Redis的注意事项
- 禁用Linux的防火墙:
- 临时禁用:service iptables stop
- 关闭开机自启:chkconfig iptables off
- redis.conf中注释掉bind 127.0.0.1(61行) ,然后 protect-mode(80行)设置为 no。
Jedis测试连通性
public class Demo01 {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("127.0.0.1",6379);
//查看服务是否运行,打出pong表示OK
System.out.println("connection is OK==========>: "+jedis.ping());
}
}
Jedis-API: Key
//key
Set<String> keys = jedis.keys("*");
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
System.out.println(key);
}
System.out.println("jedis.exists====>"+jedis.exists("k2"));
System.out.println(jedis.ttl("k1"));
Jedis-API: String
System.out.println(jedis.get("k1"));
jedis.set("k4","k4_Redis");
System.out.println("----------------------------------------");
jedis.mset("str1","v1","str2","v2","str3","v3");
System.out.println(jedis.mget("str1","str2","str3"));
Jedis-API: List
List<String> list = jedis.lrange("mylist",0,-1);
for (String element : list) {
System.out.println(element);
}
Jedis-API: set
jedis.sadd("orders","jd001");
jedis.sadd("orders","jd002");
jedis.sadd("orders","jd003");
Set<String> set1 = jedis.smembers("orders");
for (Iterator iterator = set1.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
jedis.srem("orders","jd002");
Jedis-API: hash
jedis.hset("hash1","userName","lisi");
System.out.println(jedis.hget("hash1","userName"));
Map<String,String> map = new HashMap<String,String>();
map.put("telphone","13810169999");
map.put("address","atguigu");
map.put("email","abc@163.com");
jedis.hmset("hash2",map);
List<String> result = jedis.hmget("hash2", "telphone","email");
for (String element : result) {
System.out.println(element);
}
Jedis-API: zset
jedis.zadd("zset01",60d,"v1");
jedis.zadd("zset01",70d,"v2");
jedis.zadd("zset01",80d,"v3");
jedis.zadd("zset01",90d,"v4");
Set<String> s1 = jedis.zrange("zset01",0,-1);
for (Iterator iterator = s1.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
作业完成一个手机验证码功能
- 要求:
- 1、输入手机号,点击发送后随机生成6位数字码,2分钟有效
- 2、输入验证码,点击验证,返回成功或失败
- 3、每个手机号每天只能发送3次验证码