一、NoSQL
1-1、什么是NoSQL
NoSQL = Not Only SQL(不仅仅是SQL) ,也解释为non-relational(非关系型数据库)。在NoSQL数据库中数据之间是无联系的,无关系的。数据的结构是松散的,可变的。
1-2 为什么使用NoSQL
关系型数据库的瓶颈:
1)无法应对每秒上万次的读写请求,无法处理大量集中的高并发操作。关系型数据的是IO密集的应用。硬盘IO也变为性能瓶颈
2)表中存储记录数量有限,横向可扩展能力有限,一张表最大二百多列。纵向数据可承受能力也是有限的,一张表的数据到达百万级,读写的速度就会逐渐的下降。面对海量数据,必须使用主从复制,分库分表。这样的系统架构是难以维护的。
大数据查询SQL效率极低,数据量到达一定程度时,查询时间会呈指数级别增长
3)无法简单地通过增加硬件、服务节点来提高系统性能。数据整个存储在一个数据库中的。多个服务器没有很好的解决办法,来复制这些数据。
4)关系型数据库大多是收费的,对硬件的要求较高。软件和硬件的成本花费比重较大。
1-3 NoSQL的优势
1.大数据量,高性能
NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。关系型数据库(例如MySQL)使用查询缓存。这种查询缓存在更新数据后,缓存就是失效了。在频繁的数据读写交互应用中。 缓存的性能不高。NoSQL的缓存性能要高的多。
2.灵活的数据模型
NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。尤其在快速变化的市场环境中,用户的需求总是在不断变化的。
3.高可用
NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。
NoSQL能很好的解决关系型数据库扩展性差的问题。弥补了关系数据(比如MySQL)在某些方面的不足,在某些方面能极大的节省开发成本和维护成本。
MySQL和NoSQL都有各自的特点和使用的应用场景,两者结合使用。让关系数据库关注在关系上,NoSQL关注在存储上。
4.低成本
这是大多数分布式数据库共有的特点,因为主要都是开源软件,没有昂贵的License成本
1-4 NoSQL的劣势
- 无关系,数据之间是无联系的。
- 不支持标准的SQL,没有公认的NoSQL标准
- 没有关系型数据库的约束,大多数也没有索引的概念
- 没有事务,不能依靠事务实现ACID.
- 没有丰富的数据类型(数值,日期,字符,二进制,大文本等)
二 Redis安装和使用
2-1 Redis介绍
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的Key-Value数据库. Key字符类型,其值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型,每种数据类型有自己的专属命令。所以它通常也被称为数据结构服务器。
2-2 Window上安装Redis
Windows版本的Redis是Microsoft的开源部门提供的Redis. 这个版本的Redis适合开发人员学习使用,生产环境中使用Linux系统上的Redis
1)、下载
windows版本:Releases · microsoftarchive/redis · GitHub
2)、安装
下载的Redis-x64-3.2.100.zip 解压后,放到某个目录(例如d:\tools\),即可使用。
目录结构:
3)、启动
1.、Windows7系统双击 redis-server.exe 启动Redis
2、Windows 10系统
有的机器双击redis-server.exe 执行失败,找不到配置文件,可以采用以下执行方式:
在命令行(cmd)中按如下方式执行:
D:\tools\Redis-x64-3.2.100>redis-server.exe redis.windows.conf
如图:
4)关闭
按ctrl+c 退出Redis服务程序。
2-3 Linux上安装Redis
1)、下载
wget http://219.238.7.66/files/502600000A29C8D5/download.redis.io/releases/redis-3.2.9.tar.gz
2)、安装
1.上传redis-3.2.9.tar到linux 系统。使用Xftp工具,或者使用liunx命令 rz-y
2.解压redis-3.2.9.tar到usr/local目录
3.查看解压后的文件
4.编译Redis文件, Redis是使用 c 语言编写的。 会使用gcc编译器。
在解压后的Redis目录下执行 (cd /usr/local/redis-3.2.9) make 命令。
注意事项:
1)make命令执行过程中可能报错,根据控制台输出的错误信息进行解决
2)错误一:gcc命令找不到,是由于没有安装gcc导致
解决方式:安装gcc编译器后在执行make命令
什么是 gcc ?
gcc是GNU compiler collection的缩写,它是Linux下一个编译器集合( 相当于javac ),是c或c++程序的编译器。
怎么安装gcc ?
使用yum进行安装gcc 。执行命令:yum -y install gcc
3)错误二: error: jemalloc/jemalloc.h: No such file or directory
解决方式执行 make MALLOC=libc
开始执行make
出现错误:
没有gcc , cc 编译器 ,解决安装gcc
使用yum -y install gcc
重新再编译make 。注意:安装完gcc之后,再执行make,先执行 make distclean 清理一下上次make后产生的文件。
先执行 make distclean
在执行make
执行make成功的标志
注意:在make执行之后再执行 make install,该操作则将 src下的许多可执行文件复制到/usr/local/bin 目录下,这样做可以在任意目录执行redis的软件的命令(例如启动,停止,客户端连接服务器等), make install 可以不用执行,看个人习惯。
查看make编译结果,cd src目录
注意:在make执行之后再执行 make install,该操作则将 src下的许多可执行文件复制到/usr/local/bin 目录下,这样做可以在任意目录执行redis的软件的命令(例如启动,停止,客户端连接服务器等), make install 可以不用执行,看个人习惯。
查看make编译结果,cd src目录
cd src 在执行 ls
3)、启动Redis
启动方式:
- 前台启动 ./redis-server
- 后台启动 ./redis-server & (建议使用)
第1种 前台启动
启动Redis的服务器端:切换到src 目录下执行 redis-server程序
redis应用以前台的方式启动,不能退出当前窗口, 退出窗口,应用终止。
在其他窗口查看redis启动的进程
第2种 后台启动
src目录下执行 ./redis-server & 此时关闭窗口,查看redis进程,依然存在。
查看redis进程
4)、关闭Redis
关闭方式:
① 使用redis客户端关闭, 向服务器发出关闭命令
切换到 redis-3.2.9/src/ 目录,执行 ./redis-cli shutdown
推荐使用这种方式, redis先完成数据操作,然后再关闭。
② kill pid 或者 kill -9 pid
这种不会考虑当前应用是否有数据正在执行操作,直接就关闭应用。
先使用 ps -ef | grep redis 查出进程号, 在使用 kill pid
2-4 Redis客户端
Redis客户端是一个程序,通过网络连接到Redis服务器, 在客户端软件中使用Redis可以识别的命令,向Redis服务器发送命令, 告诉Redis想要做什么。Redis把处理结果显示在客户端界面上。 通过Redis客户端和Redis服务器交互。
2-4-1 redis命令行客户端:
redis-cli (Redis Command Line Interface)是Redis自带的基于命令行的Redis客户端,用于与服务端交互,我们可以使用该客户端来执行redis的各种命令。
两种常用的连接方式:
1.直接连接redis (默认ip127.0.0.1,端口6379):./redis-cli
在redis安装目录\src, 执行 ./redis-cli
此命令是连接本机127.0.0.1 ,端口6379的redis
2.指定IP和端口连接redis:./redis-cli -h 127.0.0.1 -p 6379
-h redis主机IP(可以指定任意的redis服务器)
-p 端口号(不同的端口表示不同的redis应用)
在redis安装目录\src, 执行 ./redis-cli -h 127.0.0.1 -p 6379
2-4-2 redis远程客户端
Redis Desktop Manager:C++ 编写,响应迅速,性能好。:
github: https://github.com/uglide/RedisDesktopManager
官方地址:https://redisdesktop.com/https://redisdesktop.com/使用文档:http://docs.redisdesktop.com/en/latest/
点击“DOWNLOAD”
1.安装客户端软件
在Windows系统使用此工具,连接Linux上或Windows上的Redis , 双击此exe文件执行安装
安装后启动界面:
2.使用客户端连接Linux的Redis
连接Linux的Reids之前需要修改Redis服务器的配置信息。 Redis服务器有安全保护措施,默认只有本机(安装Redis的那台机器)能够访问。配置信息存放在Redis安装目录下的redis.conf文件。修改此文件的两个设置。
远程连接redis需要修改redis主目录下的redis.conf配置文件:
①、bind ip 绑定ip此行注释
②、protected-mode yes 保护模式改为no
使用vim 命令修改redis.conf 文件, 修改文件前备份此文件,执行cp 命令
执行 vim redis.conf
3.使用redis.conf启动Redis
修改配置文件后,需要使用配置文件重新启动Reids,默认不加载配置文件。先关闭已经启动的Redis ,使用以下命令启动Redis在Redis安装目录执行:
./redis-server ../redis.conf &
4.配置Redis Desktop Manamager(RDM),连接Redis
在RDM的主窗口,点击左下的“Connect to Redis Server”
注意:如果连接不成功,可以试着将虚拟机防火墙关闭
连接成功后:
2-4-3 redis编程客户端
1.Jedis
redis的Java编程客户端,Redis官方首选推荐使用Jedis,jedis是一个很小但很健全的redis的java客户端。通过Jedis可以像使用Redis命令行一样使用Redis。
- jedis完全兼容redis 2.8.x and 3.x.x
- Jedis源码:https://github.com/xetorthio/jedis
- api文档:http://xetorthio.github.io/jedis/
2.redis的其他编程语言客户端:
C 、C++ 、C# 、Erlang、Lua 、Objective-C 、Perl 、PHP 、Python 、Ruby 、Scala 、Go等40多种语言都有连接redis的编程客户端
2-5 Redis基本操作命令
redis默认为16个库 (在redis.conf文件可配置,该文件很重要,后续很多操作都是这个配置文件) redis默认自动使用0号库
1)、沟通命令,查看状态
redis >ping 返回 PONG
解释:输入ping,redis给我们返回PONG,表示redis服务运行正常
2)、查看当前数据库中key的数目:dbsize
语法:dbsize
作用:返回当前数据库的 key 的数量。
返回值:数字,key的数量
例:先查索引5的key个数, 再查 0 库的key个数
3)、redis默认使用16个库
Redis默认使用16个库,从0到15。 对数据库个数的修改,在redis.conf文件中databases 16
4)、切换库命令:select db
使用其他数据库,命令是 select index
例1: select 5
5)、删除当前库的数据:flushdb
6)、redis自带的客户端退出当前redis连接: exit 或 quit
2-6 Redis的Key的操作命令
1)、keys
语法:keys pattern
作用:查找所有符合模式pattern的key. pattern可以使用通配符。
通配符:
- * :表示0-多个字符 ,例如:keys * 查询所有的key。
- ?:表示单个字符,例如:wo?d , 匹配 word , wood
例1:显示所有的key
例2:使用 * 表示0或多个字符
例3:使用 ? 表示单个字符
2)exists
语法:exists key [key…]
作用:判断key是否存在
返回值:整数,存在key返回1,其他返回0. 使用多个key,返回存在的key的数量。
例1:检查指定key是否存在
例2:检查多个key
3)、expire
语法:expire key seconds
作用:设置key的生存时间,超过时间,key自动删除。单位是秒。
返回值:设置成功返回数字 1, 其他情况是 0 。
例1: 设置红灯的倒计时是5秒
4)、ttl
语法:ttl key
作用:以秒为单位,返回key的剩余生存时间(ttl: time to live)
返回值:
- -1 :没有设置key的生存时间, key永不过期。
- -2 :key不存在
- 数字:key的剩余时间,秒为单位
例1:设置redlight的过期时间是10, 查看剩余时间
5)、type
语法:type key
作用:查看key所存储值的数据类型
返回值:字符串表示的数据类型
- none (key不存在)
- string (字符串)
- list (列表)
- set (集合)
- zset (有序集)
- hash (哈希表)
例1:查看存储字符串的key :wood
例2:查看不存在的key
6)、del
语法:del key [key…]
作用:删除存在的key ,不存在的key忽略。
返回值:数字,删除的key的数量。
例1:删除指定的key
2-7 Redis的5种数据类型
1)、字符串类型 string
字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON化的对象甚至是一张图片。最大512M。
2)、哈希类型 hash
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象
3)、列表类型 list
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
4)、集合类型 set
Redis的Set是string类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数据.
5)、有序集合类型 zset (sorted set)
Redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员。
不同的是zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。
三、 Redis数据类型操作命令
3-1 字符串类型(string)
字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON化的对象甚至是一张图片。
3-1-1 基本命令
1)、set
将字符串值 value 设置到 key 中
语法:set key value
查看已经插入的key
向已经存在的key设置新的value,会覆盖原来的值
2)、get
获取 key 中设置的字符串值
语法: get key
例如:获取 username这个key对应的value
3)、incr
将 key 中储存的数字值加1,如果 key 不存在,则 key 的值先被初始化为 0 再执行 incr 操作(只能对数字类型的数据操作)
语法:incr key
例 1:操作key,值增加 1
例2:对非数字的值操作是不行的
4)、decr
将 key 中储存的数字值减1,如果 key 不存在,则么 key 的值先被初始化为 0 再执行 decr 操做(只能对数字类型的数据操作)
语法:decr key
例1:不存在的key,初值为0,再减 1 。
例2:对存在的数字值的 key ,减 1 。
先执行 incr index ,增加到 3
5)、append
语法:append key value
说明:如果 key 存在, 则将 value 追加到 key 原来旧值的末尾
如果 key 不存在, 则将key 设置值为 value
返回值:追加字符串之后的总长度
例1:追加内容到存在的key
例2:追加到不存在的key,同set key value
3-1-2 常用命令
1)、strlen
语法:strlen key
说明:返回 key 所储存的字符串值的长度
返回值:
①:如果key存在,返回字符串值的长度
②:key不存在,返回0
例1:计算存在key的字符串长度
设置中文 set k4 中文长度 , 按字符个数计算
例2:计算不存在的key
2)、getrange
语法:getrange key start end
作用:获取 key 中字符串值从 start 开始 到 end 结束 的子字符串,包括start和end, 负数表示从字符串的末尾开始, -1 表示最后一个字符
返回值:截取的子字符串。
使用的字符串 key: school, value: bjpowernode
例1: 截取从2到5的字符
例2:从字符串尾部截取,start ,end 是负数,最后一位是 -1
例3:超出字符串范围的截取 ,获取合理的子串
3)、setrange
语法:setrange key offset value
说明:用value覆盖(替换)key的存储的值从offset开始,不存在的key做空白字符串。
返回值:修改后的字符串的长度
例1:替换给定的字符串
例2:设置不存在的key
4)、mset
语法:mset key value [key value…]
说明:同时设置一个或多个 key-value 对
返回值: OK
例1:一次设置多个key, value
5)、mget
语法:mget key [key …]
作用:获取所有(一个或多个)给定 key 的值
返回值:包含所有key的列表
例1:返回多个key的存储值
例2:返回不存在的key
3-2 哈希类型hash
redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象
3-2-1 基本命令
1)hset
语法:hset key field value
作用:将哈希表 key 中的域 field 的值设为 value ,如果key不存在,则新建hash表,执行赋值,如果有field ,则覆盖值。
返回值:
①如果field是hash表中新field,且设置值成功,返回1
②如果field已经存在,旧值覆盖新值,返回0
例1:新的field
例2:覆盖旧的的field
2)、hget
语法:hget key field
作用:获取哈希表 key 中给定域 field 的值
返回值:field域的值,如果key不存在或者field不存在返回nil
例1:获取存在key值的某个域的值
例2:获取不存在的field
3)、hmset
语法:hmset key field value [field value…]
说明:同时将多个 field-value (域-值)设置到哈希表 key 中,此命令会覆盖已经存在的field,hash表key不存在,创建空的hash表,执行hmset.
返回值:设置成功返回ok, 如果失败返回一个错误
例1:同时设置多个field-value
使用redis-desktop-manager工具查看hash表 website的数据结构
4)、hmget
语法:hmget key field [field…]
作用:获取哈希表 key 中一个或多个给定域的值
返回值:返回和field顺序对应的值,如果field不存在,返回nil
例1:获取多个field的值
5)、hgetall
语法:hgetall key
作用:获取哈希表 key 中所有的域和值
返回值:以列表形式返回hash中域和域的值 ,key 不存在,返回空hash
例1:返回key对应的所有域和值
例2:不存在的key,返回空列表
6)、hdel
语法:hdel key field [field…]
作用:删除哈希表 key 中的一个或多个指定域field,不存在field直接忽略
返回值:成功删除的field的数量
例1:删除指定的field
3-2-2 常用命令
1)、hkeys
语法:hkeys key
作用:查看哈希表 key 中的所有field域
返回值:包含所有field的列表,key不存在返回空列表
例1:查看website所有的域名称
2)、hvals
语法:hvals key
作用:返回哈希表 中所有域的值
返回值:包含哈希表所有域值的列表,key不存在返回空列表
例1:显示website哈希表所有域的值
3)、hexists
语法:hexists key field
作用:查看哈希表 key 中,给定域 field 是否存在
返回值:如果field存在,返回1, 其他返回0
例1:查看存在key中field域是否存在
3-3 列表list
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)
3-3-1 基本命令
1)、lpush
语法:lpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值,从左到右的顺序依次插入到表头
返回值:数字,新列表的长度
例1:将a,b,c插入到mylist列表类型
在 redis-desktop-manager显示
插入图示:
例2:插入重复值到list列表类型
在 redis-desktop-manager显示
2)、rpush
语法:rpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表尾(最右边),各个 value 值按从左到右的顺序依次插入到表尾
返回值:数字,新列表的长度
例1:插入多个值到列表
在 redis-desktop-manager显示:
3)、lrange
语法:lrange key start stop
作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以 1 表示列表的第二个元素;start , stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 start ,stop超出列表的范围不会出现错误。
返回值:指定区间的列表
例1:返回列表的全部内容
例2:显示列表中第2个元素,下标从0开始
4)、lindex
语法:lindex key index
作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询。0 表示列表的第一个元素,以 1 表示列表的第二个元素;start , stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
返回值:指定下标的元素;index不在列表范围,返回nil
例1:返回下标是1的元素
例2:不存在的下标
5)、llen
语法:llen key
作用:获取列表 key 的长度
返回值:数值,列表的长度; key不存在返回0
例1:显示存在key的列表元素的个数
3-3-2 常用命令
1)、lrem
语法:lrem key count value
作用:根据参数 count 的值,移除列表中与参数 value 相等的元素, count >0 ,从列表的左侧向右开始移除; count < 0 从列表的尾部开始移除;count = 0移除表中所有与 value 相等的值。
返回值:数值,移除的元素个数
例1:删除2个相同的列表元素
例2:删除列表中所有的指定元素,删除所有的java
2)、lset
语法:lset key index value
作用:将列表 key 下标为 index 的元素的值设置为 value。
返回值:设置成功返回ok ; key不存在或者index超出范围返回错误信息
例1:设置下标2的value为“c”。
3)、linsert
语法:linsert key BEFORE|ALFTER pivot value
作用:将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置。key不存在,pivot不在列表中,不执行任何操作。
返回值:命令执行成功,返回新列表的长度。没有找到pivot返回 -1, key不存在返回0。
例1:修改列表arch,在值dao之前加入service
例2:操作不存在的pivot
3-4 集合类型set
redis的Set是string类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数据
3-4-1 基本命令
1)、sadd
语法:sadd key member [member…]
作用:将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略,不会再加入。
返回值:加入到集合的新元素的个数。不包括被忽略的元素。
例1:添加单个元素
2)、smember
语法:smembers key
作用:获取集合 key 中的所有成员元素,不存在的key视为空集合
例1:查看集合的所有元素
例2:查看不存在的集合
3)、sismember
语法:sismember key member
作用:判断 member 元素是否是集合 key 的成员
返回值:member是集合成员返回1,其他返回 0 。
例1:检查元素是否存在集合中
4)、scard
语法:scard key
作用:获取集合里面的元素个数
返回值:数字,key的元素个数。 其他情况返回 0 。
例1:统计集合的大小
例2:统计不存在的key
5)、srem
语法:srem key member [member…]
作用:删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略。
返回值:数字,成功删除的元素个数,不包括被忽略的元素。
例1:删除存在的一个元素,返回数字 1
例2:删除不存在的元素
3-4-2 常用命令
1)、srandmember
语法:srandmember key [count]
作用:只提供key,随机返回集合中一个元素,元素不删除,依然在集合中;提供了count时,count 正数, 返回包含count个数元素的集合, 集合元素各不相同。count 是负数,返回一个count绝对值的长度的集合, 集合中元素可能会重复多次。
返回值:一个元素;多个元素的集合
例1:随机显示集合的一个元素
例2:使用count参数, count是正数
例3:使用count参数,count是负数
2)、spop
语法:spop key [count]
作用:随机从集合中删除一个元素, count是删除的元素个数。
返回值:被删除的元素,key不存在或空集合返回nil
例如1:随机从集合删除一个元素
例2:随机删除指定个数的元素
3-5 有序集合类型 zset (sorted set)
redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员。
不同的是zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。
3-5-1 基本命令
1)、zadd
语法:zadd key score member [score member…]
作用:将一个或多个 member 元素及其 score 值加入到有序集合 key 中,如果member存在集合中,则更新值;score可以是整数或浮点数
返回值:数字,新添加的元素个数
例1:创建保存学生成绩的集合
例2:使用浮点数作为score
2)、zrange
语法:zrange key start stop [WITHSCORES]
作用:查询有序集合,指定区间的内的元素。集合成员按score值从小到大来排序。 start, stop都是从0开始。0是第一个元素,1 是第二个元素,依次类推。以 -1表示最后一个成员,-2 表示倒数第二个成员。WITHSCORES选项让score和value一同返回。
返回值:自定区间的成员集合
例1:显示集合的全部元素,不显示score,不使用WITHSCORES
例2:显示集合全部元素,并使用WITHSCORES
例3:显示第0,1二个成员
例4:排序显示浮点数的score
3)、zrevrange
语法:zrevrange key start stop [WITHSCORES]
作用:返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。其它同zrange命令。
返回值:自定区间的成员集合
例1:成绩榜
4)、zrem
语法:zrem key member [member…]
作用:删除有序集合 key 中的一个或多个成员,不存在的成员被忽略
返回值:被成功删除的成员数量,不包括被忽略的成员。
例1:删除指定一个成员wangwu
5)、zcard
语法:zcard key
作用:获取有序集 key 的元素成员的个数
返回值:key存在返回集合元素的个数, key不存在,返回0
例1:查询集合的元素个数
3-5-2 常用命令
1)、zrangebyscore
语法:zrangebyscore key min max [WITHSCORES ] [LIMIT offset count]
作用:获取有序集 key 中,所有 score 值介于 min 和 max 之间(包括min和max)的成员,有序成员是按递增(从小到大)排序。
min ,max是包括在内 , 使用符号 ( 表示不包括。 min,max 可以使用 -inf ,+inf表示最小和最大
limit 用来限制返回结果的数量和区间。
withscores 显示score 和 value
返回值:指定区间的集合数据
使用的准备数据
例1:显示指定具体区间的数据
例2:显示指定具体区间的集合数据,开区间(不包括min,max)
例3:显示整个集合的所有数据
例4:使用limit
增加新的数据:
显示从第一个位置开始,取一个元素。
2)、zrevrangebyscore
语法:zrevrangebyscore key max min [WITHSCORES ] [LIMIT offset count]
作用:返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。其他同zrangebyscore
例1:查询工资最高到3000之间的员工
3)、zcount
语法:zcount key min max
作用:返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量
例1:求工资在3000-5000的员工数量
四、高级话题
4-1 Redis事务
4-1-1 什么是事务
事务是指一系列操作步骤,这一系列的操作步骤,要么完全地执行,要么完全地不执行。
Redis中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令,redis事务保证这些命令被执行时中间不会被任何其他操作打断。
4-1-2 事务操作的命令
1)、multi
语法: multi
作用:标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中。
返回值:总是返回ok
2)、exec
语法:exec
作用:执行所有事务块内的命令
返回值:事务内的所有执行语句内容,事务被打断(影响)返回nil
3)、discard
语法:discard
作用:取消事务,放弃执行事务块内的所有命令
返回值:总是返回ok
4)、watch
语法:watch key [key ...]
作用:监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
返回值:总是返回ok
5)、unwatch
语法:unwatch
作用:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了
返回值:总是返回ok
4-1-3 事务的实现
1)、正常执行事务
事务的执行步骤: 首先开启事务, 其次向事务队列中加入命令,最后执行事务提交
例1:事务的执行:
1)multi : 用multi命令告诉Redis,接下来要执行的命令你先不要执行,而是把它们暂时存起来 (开启事务)
2)sadd works john 第一条命令进入等待队列(命令入队)
3)sadd works rose 第二条命令进入等待队列(命令入队)
4)exce 告知redis执行前面发送的两条命令(提交事务)
查看works集合
2)、事务执行exec之前,入队命令错误(语法错误;严重错误导致服务器不能正常工作(例如内存不足)),放弃事务。
执行事务步骤:
1)MULTI 正常命令
2)SET key value 正常命令
3)INCR 命令语法错误
4)EXEC 无法执行事务,那么第一条正确的命令也不会执行,所以key的值不会设置成功
结论:事务执行exec之前,入队命令错误,事务终止,取消,不执行。
3)、事务执行exec命令后,执行队列命令,命令执行错误,事务提交
执行步骤:
1)MULTI 正常命令
2)SET username zhangsan 正常命令
3)lpop username 正常命令,语法没有错误,执行命令时才会有错误。
4)EXEC 正常执行 ,发现错误可以在事务提交前放弃事务,执行discard.
结论:在exec执行后的所产生的错误, 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。
Redis 在事务失败时不进行回滚,而是继续执行余下的命令。
Redis这种设计原则是:Redis 命令只会因为错误的语法而失败(这些问题不能在入队时发现),或是命令用在了错误类型的键上面,失败的命令并不是Redis导致,而是由编程错误造成的,这样错误应该在开发的过程中被发现,生产环境中不应出现语法的错误。就是在程序的运行环境中不应该出现语法的错误。而Redis能够保证正确的命令一定会被执行。再者不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
4)、放弃事务
执行步骤:
1) MULTI 开启事务
2) SET age 25 命令入队
3) SET age 30 命令入队
4) DISCARD 放弃事务,则命令队列不会被执行
例1:
5)、Redis的watch机制
A.Redis的WATCH机制
WATCH机制原理:
WATCH机制:使用WATCH监视一个或多个key , 跟踪key的value修改情况, 如果有key的value值在事务EXEC执行之前被修改了, 整个事务被取消。EXEC 返回提示信息,表示事务已经失败。
WATCH机制使的事务EXEC变的有条件,事务只有在被WATCH的key没有修改的前提下才能执行。不满足条件,事务被取消。使用 WATCH 监视了一个带过期时间的键, 那么即使这个键过期了, 事务仍然可以正常执行
大多数情况下, 不同的客户端会访问不同的键, 相互同时竞争同一key的情况一般都很少, 乐观锁能够以很好的性能解决数据冲突的问题。
B.何时取消key的监视(WATCH)?
① WATCH 命令可以被调用多次。 对键的监视从 WATCH 执行之后开始生效,直到调用 EXEC 为止。不管事务是否成功执行, 对所有键的监视都会被取消。
② 当客户端断开连接时, 该客户端对键的监视也会被取消。
③ UNWATCH 命令可以手动取消对所有键的监视
C.WATCH的事例
执行步骤:
首先启动redis-server , 在开启两个客户端连接。 分别叫 A 客户端 和 B客户端。
启动Redis服务器
A客户端(红色):WATCH某个key ,同时执行事务
B 客户端(黄色):对A客户端WATCH的key修改其value值。
1.在A客户端设置key : str.lp登录人数为10
2.在A客户端监视 key : str.lp
3.在A客户端开启事务 multi
4.在A客户端修改 str.lp的值为11
5.在B客户端修改 str.lp的值为 15
6.在A客户端执行事务exec
7.在A客户端查看 str.lp值,A客户端执行的事务没有提交,因为WATCH的str.lp的值已经被修改了, 所有放弃事务。
例1:乐观锁
4-2 持久化
4-2-1 持久化概述
持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而放在磁盘就算是一种持久化。
Redis的数据存储在内存中,内存是瞬时的,如果linux宕机或重启,又或者Redis崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
4-2-2 持久化方式
(一)、RDB方式
1)、什么是RDB方式?
Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是dump.rdb。RDB技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响Redis的正常使用。RDB恢复数据时比其他AOF速度快。
2)、如何实现
RDB方式的数据持久化,仅需在redis.conf文件中配置即可,默认配置是启用的。
在配置文件redis.conf中搜索 SNAPSHOTTING, 查找在注释开始和结束之间的关于RDB的配置说明。配SNAPSHOTTING置地方有三处。
①:配置执行RDB生成快照文件的时间策略。
对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个key改动”这一条件被满足时, 自动保存一次数据集。
配置格式:save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
②:dbfilename:设置RDB的文件名,默认文件名为dump.rdb
③:dir:指定RDB文件的存储位置,默认是 ./ 当前目录
配置步骤:
①:查看 ps -ef | grep redis ,如果redis服务启动,先停止。
②:修改redis.conf 文件, 修改前先备份,执行 cp redis.conf bak_redis.conf
查看默认启用的RDB文件
③:编辑redis.conf 增加save配置, 修改文件名等。vim redis.conf
修改的内容:
把原来的默认的dump.rdb删除,修改redis.conf后,重新启动redis
④:在20秒内容,修改三个key的值
⑤:查看生成的rdb文件
3)、总结
优点:由于存储的是数据快照文件,恢复数据很方便,也比较快
缺点:
1)会丢失最后一次快照以后更改的数据。如果你的应用能容忍一定数据的丢失,那么使用rdb是不错的选择;如果你不能容忍一定数据的丢失,使用rdb就不是一个很好的选择。
2)由于需要经常操作磁盘,RDB 会分出一个子进程。如果你的redis数据库很大的话,子进程占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别),如果你的数据库超级大并且你的服务器CPU比较弱,有可能是会达到一秒。
(二)、AOF方式
1)、什么是AOF方式
Append-only File(AOF),Redis每次接收到一条改变数据的命令时,它将把该命令写到一个AOF文件中(只记录写操作,读操作不记录),当Redis重启时,它通过执行AOF文件中所有的命令来恢复数据。
2)、如何实现
AOF方式的数据持久化,仅需在redis.conf文件中配置即可
配置项:
①:appendonly:默认是no,改成yes即开启了aof持久化
②:appendfilename:指定AOF文件名,默认文件名为appendonly.aof
③:dir : 指定RDB和AOF文件存放的目录,默认是 ./
④:appendfsync:配置向aof文件写命令数据的策略:
no:不主动进行同步操作,而是完全交由操作系统来做(即每30秒一次),比较快但不是很安全。
always:每次执行写入都会执行同步,慢一些但是比较安全。
everysec:每秒执行一次同步操作,比较平衡,介于速度和安全之间。这是默认项。
⑤:auto-aof-rewrite-min-size:允许重写的最小AOF文件大小,默认是64M 。当aof文件大于64M时,开始整理aop文件, 去掉无用的操作命令。缩小aop文件。
例1:
①:停止运行的redis , 备份要修改的redis.conf
②:查看redis安装目录/src下有无 .aof 文件。 默认是在redis的当前目录
③:编辑 redis.conf
设置 appendonly 为 yes 即可。
查看 appendfsync 的当前策略。
查看 appendfilname的文件名称
④:在redis客户端执行 写入命令
⑤ 查看aof文件
2)、总结
1)append-only 文件是另一个可以提供完全数据保障的方案;
2)AOF 文件会在操作过程中变得越来越大。比如,如果你做一百次加法计算,最后你只会在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录对最终的结果是无用的;但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小
3)可以同时使用这两种方式,redis默认优先加载aof文件(aof数据最完整);
4-3 主从复制
4-3-1 主从复制--读写分离
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,那该怎么实现呢? Redis的主从复制。
Redis提供了复制(replication)功能来自动实现多台redis服务器的数据同步(每天19点 新闻联播,基本从cctv1-8,各大卫视都会播放)
我们可以通过部署多台redis,并在配置文件中指定这几台redis之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即master/slave,并且redis默认master用于写,slave用于读,向slave写数据会导致错误
(一)、Redis主从复制实现(master/salve)
方式1:修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从而构成主从复制的关系
方式2: ./redis-server --slaveof <master-ip> <master-port>,在启动redis时指定当前服务成为某个主Redis服务的从Slave
方式1的实现步骤:
模拟多Reids服务器, 在一台已经安装Redis的机器上,运行多个Redis应用模拟多个Reids服务器。一个Master,两个Slave.
1)、新建三个Redis的配置文件
如果Redis启动,先停止。
作为Master的Redis端口是 6380
作为Slaver的Redis端口分别是6382 , 6384
从原有的redis.conf 拷贝三份,分别命名为 redis6380.conf, redis6382.conf , redis6384.conf
2)、编辑Master配置文件
编辑Master的配置文件redis6380.conf : 在空文件加入如下内容
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6380
pidfile /var/run/redis_6380.pid
logfile 6380.log
dbfilename dump6380.rdb
配置项说明:
include : 包含原来的配置文件内容。/usr/local/redis-3.2.9/redis.conf按照自己的目录设置。
daemonize:yes 后台启动应用,相当于 ./redis-server & , &的作用。
port : 自定义的端口号
pidfile : 自定义的文件,表示当前程序的pid ,进程id。
logfile:日志文件名
dbfilename:持久化的rdb文件名
3)、编辑Slave配置文件
编辑Slave的配置文件redis6382.conf 和redis6384.conf: 在空文件加入如下内容
①:redis6382.conf:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6382
pidfile /var/run/redis_6382.pid
logfile 6382.log
dbfilename dump6382.rdb
slaveof 127.0.0.1 6380
配置项说明:
slaveof : 表示当前Redis是谁的从。当前是127.0.0.0 端口6380这个Master的从。
②:redis6384.conf:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6384
pidfile /var/run/redis_6384.pid
logfile 6384.log
dbfilename dump6384.rdb
slaveof 127.0.0.1 6380
4)、启动服务器 Master/Slave都启动
启动方式 ./redis-server 配置文件
启动Redis,并查看启动进程
5)、查看配置后的服务信息
命令:
①: Redis客户端使用指定端口连接Redis服务器
./redis-cli -p 端口
②:查看服务器信息
info replication
登录到Master:6380
查看当前服务信息
在客户端的Redis内执行命令 info replication
Master服务的查看结果:
在新的Xshell窗口分别登录到6382 ,6384查看信息
6384也登录内容同6382.
6)、向Master写入数据
在6380执行flushall 清除数据,避免干扰的测试数据。 生产环境避免使用。
7)、在从Slave读数据
6382,6384都可以读主Master的数据,不能写
Slave写数据失败
(二)、容灾处理
当Master服务出现故障,需手动将slave中的一个提升为master, 剩下的slave挂至新的master上(冷处理:机器挂掉了,再处理)
命令:
①:slaveof no one,将一台slave服务器提升为Master (提升某slave为master)
②:slaveof 127.0.0.1 6381 (将slave挂至新的master上)
执行步骤:
1)、将Master:6380停止(模拟挂掉)
2)、选择一个Slave升到Master,其它的Slave挂到新提升的Master
3)、将其他Slave挂到新的Master
在Slave 6384上执行
现在的主从(Master/Slave)关系:Master是6382 , Slave是6384
查看6382:
4)、原来的服务器重新添加到主从结构中
6380的服务器修改后,从新工作,需要把它添加到现有的Master/Slave中
先启动6380的Redis服务
连接到6380端口
当前服务挂到Master上
5)、查看新的Master信息
在6382执行:
现在的Master/Slaver关系是:
Master: 6382
Slave: 6380、6384
(三)、操作命令
进入客户端需指定端口:./redis-cli -p 6380
不配置启动默认都是主master
info replication 查看redis服务器所处角色
(四)、总结
1、一个master可以有多个slave
2、slave下线,读请求的处理性能下降
3、master下线,写请求无法执行
4、当master发生故障,需手动将其中一台slave使用slaveof no one命令提升为master,其它slave执行slaveof命令指向这个新的master,从新的master处同步数据
5、主从复制模式的故障转移需要手动操作,要实现自动化处理,这就需要Sentinel哨兵,实现故障自动转移
4-3-2 高可用Sentinel哨兵
Sentinel哨兵是redis官方提供的高可用方案,可以用它来监控多个Redis服务实例的运行情况。Redis Sentinel 是一个运行在特殊模式下的Redis服务器。Redis Sentinel是在多个Sentinel进程环境下互相协作工作的。
Sentinel系统有三个主要任务:
- 监控:Sentinel不断的检查主服务和从服务器是否按照预期正常工作。
- 提醒:被监控的Redis出现问题时,Sentinel会通知管理员或其他应用程序。
- 自动故障转移:监控的主Redis不能正常工作,Sentinel会开始进行故障迁移操作。将一个从服务器升级新的主服务器。 让其他从服务器挂到新的主服务器。同时向客户端提供新的主服务器地址。
Sentinel配置
1)、Sentinel配置文件
复制三份sentinel.conf文件:
Sentinel系统默认 port 是26379 。三个配置port分别设置为 26380 , 26382 , 26384 。三个文件分别命名:
- sentinel26380.conf
- sentinel26382.conf
- sentinel26384.conf
执行复制命令 cp sentinel.conf xxx.conf
2)、三份sentinel配置文件修改:
1、修改 port 26380、 port 26382、 port 26384
2、修改 sentinel monitor mymaster 127.0.0.1 6380 2
格式:sentinel monitor <name> <masterIP> <masterPort> <Quorum投票数>
Sentinel监控主(Master)Redis, Sentinel根据Master的配置自动发现Master的Slave,Sentinel默认端口号为26379 。
sentinel26380.conf
1) 修改port
2)修改监控的master地址
sentinel26382.conf 修改port 26382 , master的port 6382
sentinel26384.conf 修改port 26384 , master的port 6382
3)、启动主从(Master/Slave)Redis
启动Reids
查看Master的配置信息
连接到6382端口
使用 info 命令查看 Master/Slave
4)、启动Sentinel
redis安装时make编译后就产生了redis-sentinel程序文件,可以在一个redis中运行多个sentinel进程。
启动一个运行在Sentinel模式下的Redis服务实例
./redis-sentinel sentinel配置文件
执行以下三条命令,将创建三个监视主服务器的Sentinel实例:
./redis-sentinel ../sentinel26380.conf
./redis-sentinel ../sentinel26382.conf
./redis-sentinel ../sentinel26384.conf
在XShell开启三个窗口分别执行
5)、主Redis不能工作
让Master的Redis停止服务, 执行shutdown
先执行 info replication 确认Master的Redis ,再执行shutdown
查看当前Redis的进程情况
6)、Sentinel的起作用
在Master执行shutdown后, 稍微等一会 Sentinel要进行投票计算,从可用的Slave选举新的Master。
查看Sentinel日志,三个Sentinel窗口的日志是一样的。
查看新的Master
查看原Slave的变化
7)、新的Redis加入Sentinel系统,自动加入Master
重新启动6382
查看6384的信息
测试数据:在Master写入数据
在6382上读取数据,不能写入
8)、监控
1)Sentinel会不断检查Master和Slave是否正常
2)如果Sentinel挂了,就无法监控,所以需要多个哨兵,组成Sentinel网络,一个健康的
Sentinel至少有3个Sentinel应用。 彼此在独立的物理机器或虚拟机。
3)监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监控服务器的信息
4)当一个Sentinel认为被监控的服务器已经下线时,它会向网络中的其它Sentinel进行确认,判断该服务器是否真的已经下线
5)如果下线的服务器为主服务器,那么Sentinel网络将对下线主服务器进行自动故障转移,通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转移到新的主服务器下,以此来让系统重新回到正常状态
6)下线的旧主服务器重新上线,Sentinel会让它成为从,挂到新的主服务器下
9)、总结
主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降,Master下线,写请求无法执行
Sentinel会在Master下线后自动执行故障转移操作,提升一台Slave为Master,并让其它Slave成为新Master的Slave
4-4 安全设置
4-4-1、设置密码
访问Redis默认是没有密码的,这样不安全,任意用户都可以访问。可以启用使用密码才能访问Redis。 设置Redis的访问密码,修改redis.conf 中这行requirepass 密码。密码要比较复杂,不容易破解,而且需要定期修改。因为redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K 次的密码尝试,需要指定非常非常强大的密码来防止暴力破解。
1)、开启访问密码设置
修改redis.conf , 使用vim命令。 找到requirepass行去掉注释,requirepass空格后就是密码。
例1:设置访问密码是 123456 ,这是练习使用,生产环境要设置复杂密码
修改redis.conf,文件480行左右。原始内容:
修改后:
查看修改结果:
2)、访问有密码的Redis
如果Redis已经启动,关闭后,重新启动。
访问有密码的Redis两种方式:
①:在连接到客户端后,使用命令 auth 密码 , 命令执行成功后,可以正常使用Redis
②:在连接客户端时使用 -a 密码。例如 ./redis-cli -h ip -p port -a password
启动Redis
使用 ① 访问
输入命令 auth 密码
使用 ② 方式
4-4-2、绑定Ip
修改redis.conf文件,把# bind 127.0.0.1前面的注释#号去掉,然后把127.0.0.1改成允许访问你redis服务器的ip地址,表示只允许该ip进行访问。多个ip使用空格分隔。
例如 bind 192.168.1.100 192.168.2.10
4-4-3、修改默认端口
修改redis的端口,这一点很重要,使用默认的端口很危险,redis.conf中修改port 6379 将其修改为自己指定的端口(可随意),端口1024是保留给操作系统使用的。用户可以使用的范围是1024-65535
使用 -p 参数指定端口,例如:./redis-cli -p 新设置端口