应用程序通过数据访问层(DAL)使用数据库
问题:
把常用数据放入缓存中, 并对数据库进行垂直拆分,即按照业务将表进行分类,分布到不同的数据库上面,减轻访问压力
问题:读写集中在一个数据库上让数据库不堪重负
从库是主库的镜像,主数据库负责写,从数据库负责读
问题:在高并发下会出现严重的锁问题
对数据库的表进行水平拆分,即把一张表的不同部分存放到不同数据库中,并布置到集群中
分布式:不同的多台服务器上部署不同的服务模块
集群:不同的多台服务器上部署相同的服务模块
经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢。 MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难 。
如果要对用户数据进行挖掘,则SQL数据库已经不适合这些应用了,所以使用NoSQL数据库。NoSQL=Not Only SQL,泛指非关系型数据库。这些类型的数据存储不需要固定的模式,无需多余的操作就可以横向扩展。NoSQL数据库的一个共同特点就是去掉关系型数据库的关系型特性,数据之间无关系,这样就容易拓展。NoSQL无需实现为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系型数据库中增删字段是一件非常麻烦的事情。
3V
3高
高并发
高可扩
高性能
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点
分布式系统中分区容错性P是必须要有的,所以在强一致性C和高可用性A中选择
CA:传统关系型数据库
AP:大多数网站架构的选择
CP:Redis、MongoDB
为了解决关系型数据库强一致性引起的问题而引起的可用性降低而提出的解决方案
其思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上的改观。
Redis:REmote Dictionary Server(远程字典服务器)。是开源的,用C语言编写的,遵守BSD协议,是一个高性能的(key-value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库。
与其他key-value的NoSQL数据库相比,Redis有三个特点:
Redis中文官网
Redis官网
下载安装包安装
redis-x.x.x.tar.gz
后放入/opt
目录下tar -zxvf redis-x.x.x.tar.gz
进行解压,解压后出现文件夹redis-x.x.x
redis-x.x.x
make
命令(需要安装gcc)
make
失败,报缺少Jemalloc/jemalloc.h
,则运行make distclean
后再make
make
完成后继续执行make install
命令/usr/local/bin
安装时碰到两个问题,一个是redis.conf文件没权限,用chmod 777 redis.conf
命令更改权限即可,另一个是缺少日志文件,解决办法是在相应的路径下创建对应的日志文件,并更改其权限即可。注意执行命令时可能需要使用root权限。
使用命令安装(推荐使用)
sudo apt-get update sudo apt-get install redis-server
此时的redis配置文件目录为/etc/redis/redis.conf
/etc/redis/redis-x.x.x
目录下执行redis-server redis.conf
,使用不同的配置文件时,启动起来的redis是不同的redis-cli -p 6379
启动Redis客户端set hello world
,再输入get hello
得到hello对应的值worldps -ef|grep redis
查看是否启动成功exit
退出select <dbid>
切换数据库,如select 5
DBSIZE
查看key的个数,Redis下支持Tab键自动补全,keys *
查看所有的keyFLUSHDB
删除当前库,FLUSHALL
删除所有库keys *
:查看所有键exists key
:判断某个key是否存在move key 数据库名
:把key剪切到指定数据库expire key 时间
:为key设定过期时间,单位是秒,过期后key被删除ttl key
:查看还有多少秒过期,-1表示永不过期,-2表示已过期(不存在)type key
:查看key的类型dump key
:序列化给定key,并返回被序列化的值expireat key 时间戳
:和expire租用类似,都是为key设置过期时间,不同的是参数为Unix时间戳expire key 毫秒
:设置key过期的时间,以毫秒为单位expireat key 毫秒时间戳
:设置key过期的时间戳,以毫秒为单位keys 模式
:查找所有符合给定模式的key,所谓模式就是正则表达式persist key
:移除key的过期时间,key将持久保持pttl key
:以毫秒为单位返回key的剩余过期时间randomkey
:从当前数据库随机返回一个keyrename key 新键名
:修改key的名称renamenx key 新键名
:仅当新键名不存在时,将key修改为新键名与Memcached一样的类型,一个key对应一个value。是二进制安全的,意思是string可以包含任何数据。字符串value最多可以是512M
一个键值对集合,其键是string类型,其值是一个键值对,类似于java中的Map<String, Object>,特别适合用于存储对象
是简单的字符串列表,底层实际是个链表,按照插入顺序排序,可以添加一个元素到列表的头部或尾部。如果键不存在会创建新链表,反之新增内容。如果值全移除,对应的键也就消失了。
是string的无序集合,通过HashTable实现的
与Set不同的是每个元素都会关联一个double类型的分数。redis正是通过分数䣂为集合中的元素进行从小到大的排序,zset的元素是唯一的,但分数是可以重复的
set key value
:设置指定字符串的值
get key
:获取指定字符串的值
del key
:删除字符串
append key value
:如果key已经存在并且是一个字符串,append命令将给定的值追加到字符串原来值的末尾
strlen key
:返回key所存储的字符串值的长度
incr key
:将key中存储的数字值增加1
incrby key 增量值
:将key所存储的值加上给定的增量值(一定是数字)
decr key
:将key中存储的数字值减1
decrby key 减量值
:将key所存储的值减去给定的减量值(一定是数字)
getrange key 起始值 终止值
:返回key中字符串值的子字符,0到-1表示全部
setrange key 偏移量 value
:用给定的值覆盖给定key所储存的字符串值,从偏移量开始
setex key 时间 value
:(set with expire),将值关联到key,并设置key的过期时间,以秒为单位
setnx key value
:(set if not exist),只有在key不存在时设置key的值
mset key1 value1 [key2 value2...]
:同时设置一个或多个键值对
mget key1 [key2...]
:获取所有(一个或多个)给定key的值
msetnx key1 value1 [key2 value2...]
:同时设置一个或多个键值对,当且仅当所有给定的key都不存在
getset key value
:将给定的key的值设为给定的值,并返回key的旧值
getbit key 偏移量
:对key所储存的字符串值,获取指定偏移量上的位(bit)setbit key 偏移量 value
:对key所储存的字符串值,设置或清除指定偏移量上的位psetex key 毫秒 value
:与setex命令类似,但以毫秒为单位设置key的生存时间incrbyfloat key 增量值
:将key所存储的值加上给定的浮点数增量值hset key 字段 value
:将哈希表中的字段值设为给定值
hget key 字段
:获取存储在哈希表中指定字段的值
hmset key 字段1 value1 [字段2 value2...]
:同时将多个字段-值对设置到哈希表中
hmget key 字段1 [字段2...]
:获取所有给定的字段的值
hgetall key
:获取哈希表中所有的字段和值
hdel key 字段1 [字段2...]
:删除一个或多个哈希表字段
hlen key
:获取哈希表中字段的数量
hexists key 字段
:查看哈希表中指定字段是否存在
hkeys key
:获取哈希表中的所有字段
hvals key
:获取哈希表中的所有值
hincrby key 字段 增量值
:为哈希表的指定字段的整数值加上增量值
hincrbyfloat key 字段 增量值
:为哈希表的指定字段的浮点数数值加上增量值
hsetnx key 字段 value
:只有在字段不存在时,才设置哈希表的字段值
hscan key 游标 [MATCH patter] [COUNT count]
:迭代哈希表中的键值对lpush key value1 [value2...]
:将一个或多个值插入到列表头部
rpush key value1 [value2...]
:在列表中添加一个或多个值
lrange key 起始值 终止值
:获取列表下标在指定范围内的元素,lrange key 0 -1
查看全部元素
lpop key
:移除并获取列表的第一个元素
rpop key
:移除并获取列表最后一个元素
lindex key 索引值
:通过索引获取列表中的元素
llen key
:获取列表长度
lrem key 个数 value
:移除指定个数个指定值的列表元素
ltrim key 起始值 终止值
:对一个列表进行修剪,即让列表只保留下标在指定区间内的元素,其他的删除
rpoplpush 源列表 目的列表
:移除列表的最后一个元素,并将该元素添加到另一个列表,并返回该值
lset key 索引 value
:通过索引设置列表元素的值
linsert key before|after 目标值 插入值
:在列表的元素前或后插入元素,若存在多个同值元素,则只在第一个后面插入
blpop key1 [key2] 超时值
:移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止brpop key1 [key2] 超时值
:移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止brpoplpush 源列表 目的列表 超时值
:从列表中弹出一个值,将弹出的元素插入到另一个列表中并返回它,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止lpushx key value
:将一个或多个值插入到已存在的列表头部rpushx key value
:为已存在的列表添加值sadd key 元素1 [元素2...]
:向集合添加一个或多个元素,返回成功添加的元素个数
smembers key
:返回集合中的所有元素
sismember key 元素
:判断元素是否在集合的元素
scard key
:获取集合的元素数
srem key 元素1 [元素2...]
:移除集合中一个或多个元素,返回成功移除的个数
srandmember key [个数]
:随机返回集合中指定个数个元素
spop key
:移除并返回集合中的一个随机元素
smove 源集合 目的集合 元素
:将元素从源集合移动到目的集合
sdiff key1 [key2]
:返回给定所有集合的差集,在第一个集合中,但不在后面的任何一个集合中
sinter key1 [key2...]
:返回给定所有集合的交集
sunion key1 [key2...]
:返回所有给定集合的并集
sdiffstore 目的集合 key1 [key2...]
:返回给定所有集合的差集并存储在目标集合中sinterstore 目的集合 key1 [key2]
:返回给定所有集合的交集并存储在目标集合中sunionstore 目的集合 key1 [key2]
:所有给定结合的并集存储在目的集合中sscan key 游标 [MATCH pattern] [COUNT count]
:迭代集合中的元素zadd key 分数1 元素1 [分数2 元素2]
:向有序集合中添加一个或多个元素,或者更新已存在的元素的分数
zrange key 起始值 终止值 [WITHSCORES]
:通过索引区间返回有序集合中指定区间内的元素,带withscores时也显示分数
zrangebyscore key 最小值 最大值 [WITHSCORES] [LIMIT]
:通过分数区间返回有序集合指定区间内的元素。区间默认前闭后闭,最小值和最大值前可以加括号(
表示不包含该数字,limit的作用是返回限制,类似于分页,如limit 2 3
即从下标为2的开始截取3个返回
zrem key 元素 [元素...]
:移除集合中的一个或多个元素
zcard key
:获取有序集合的元素数
zcount key 最小值 最大值
:计算在有序集合中指定区间分数的元素数,最小值和最大值前可以加括号(
表示不包含该数字
zrank key 元素
:返回有序集合中指定元素按分数升序排序后的索引
zscore key 元素
:返回有序集合中指定元素的分数值
zrevrank key 元素
:返回有序集合中指定元素按分数降序排序后的索引
zrevrange key 起始值 终止值 [WITHSCORES]
:先按分数降序排序,然后取指定下标区间的元素
zrevrangebyscore key 最大值 最小值 [WITHSCORES]
:先按分数降序排序,然后取指定分数区间内的元素
zincrby key 增量值 元素
:有序集合中对指定元素的分数加上增量值zinterstore 目的有序集合 numkeys key [键...]
:计算给定的一个或多个有序集合的交集并将结果存储在新的有序集合中zlexcount key 最小值 最大值
:在有序集合中数计算指定字典区间内元素数量zrangebylex key 最小值 最大值 [LIMIT 偏移量 个数]
:通过字典区间返回有序集合的元素zremrangebylex key 最小值 最大值
:移除有序集合中给定的字典区间的所有元素zremrangebyrank key 起始值 终止值
:移除有序集合中给定的排名区间的所有元素zremrangebyscore key 最小值 最大值
:移除有序集合中给定的分数区间的所有元素zunionstore 目标有序集合 numkeys key1 [key2...]
:计算给定的一个或多个有序集合的并集,那个存储在新的key中zscan key 游标 [MATCH pattern] [COUNT count]
:迭代有序集合中的元素(包括元素和元素的分数)Redis的配置文件redis.conf
位于目录/etc/redis
下,配置文件中大小写不敏感,且1k和1kb是不一样的
Redis可以通过config get 配置设置名
和config set 配置设置名
来获取和设置配置文件中某选项的值
通过include包含其他的配置文件,如include /path/to/other.conf
daemonize yes
:以守护进程的方式运行,默认为nopidfile /var/run/redis.pid
: 当 Redis 以守护进程方式运行时,Redis 默认会把 pid 写入/var/run/redis.pid
文件,可以通过pidfile
指定tcp-backlog 511
:设置tcp的backlog,backlog其实是一个链接队列,backlog队列总和=未完成三次握手队列+已经完成三次握手队列。在高并发环境下需要一个高backlog值来避免客户端连接的问题port 6379
: 指定 Redis 监听端口timeout 300
: 当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能bind 127.0.0.1
:绑定的主机的地址,可绑定多个tcp-keepalive 0
:单位为秒,如果设置为0,则不会进行Keepalive检测,建议设为60秒loglevel notice
: 指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 noticelogfile stdout
: 日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
Syslog-enabled no
:是否打开系统日志Syslog-ident redis
:指定系统日志标识Syslog-facility local0
:指定syslog设备,值可以是user或local0~local7databases 16
: 设置数据库的数量save <seconds> <changes>
: 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合。默认配置文件中提供了3个条件,有一个满足即可触发。也可以用save
命令手动备份
save 900 1
: 900 秒(15 分钟)内有 1 个更改save 300 10
: 300 秒(5 分钟)内有 10 个更改save 60 10000
: 60 秒内有 10000 个更改Stop-writes-on-bgsave-error yes
:当后台保存发生错误时停止写入。如果设为no,则表示不在乎数据不一致或有其他的手段发现和控制rdbcompression yes
: 指定存储至本地数据库时是否压缩数据,默认为 yes, 可以关闭该选项,但会导致数据库文件变的巨大rdbchecksum yes
:在存储快照后,可以让redis使用CRC64算法来进行数据校验,但会增加10%的性能消耗dbfilename dump.rdb
: 指定本地数据库文件名dir ./
: 指定本地数据库存放目录slaveof <masterid> <masterport>
: 置当本机为 slave 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步masterauth <master-password>
: 当 master 服务设置了密码保护时,slave服务连接 master 的密码requriepass <password>
: 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 auth
命令提供密码,默认关闭maxclients 128
: 设置同一时间最大客户端连接数, 0表示不作限制maxmemory <bytes>
: 指定 Redis 最大内存限制, 达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Keyappendonly no
: 指定是否在每次更新操作后进行日志记录,Redis 在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。 默认为 noappendfilename appendonly.aof
: 指定更新日志文件名appendfsync everysec
: 指定更新日志条件,有3个可选值
no
:表示等操作系统进行数据缓存同步到磁盘(快)always
:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)everysec
:表示每秒同步一次(折中,默认值)No-appendfsync-on-rewrite
:重写时是否可以运用Appendfsync,用默认no即可,保证数据安全性auto-aof-rewrite-percentage 100
:设置重写的基准值,当AOF文件为上次重写时AOF文件的一倍是才重写auto-aof-rewrite-min-size 64mb
:设置重写的基准值,当AOF文件超过64MB时才会重写activerehashing yes
: 指定是否激活重置哈希,默认为开启以下是在自己的redis.conf文件中没有找到,但是在其他参考资料中提到的配置选项
vm-enabled no
: 指定是否启用虚拟内存机制,默认值为 no, VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中vm-swap-file /tmp/redis.swap
: 虚拟内存文件路径, 不可多个 Redis 实例共享vm-max-memory 0
: 将所有大于 vm-max-memory 的数据存入虚拟内存vm-page-size 32
: Redis swap 文件分成了很多的 page,一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享,vm-page-size 是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page 大小最好设置为 32 或者 64bytevm-pages 134217728
: 设置 swap 文件中的 page 数量vm-max-threads 4
: 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟glueoutputbuf yes
: 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启hash-max-zipmap-entries 64
: 指定在超过一定的数量时,采用一种特殊的哈希算法hash-max-zipmap-value 512
:指定最大的元素超过某一临界值时,采用一种特殊的哈希算法config get requirepass
:获取密码
config set requirepass "123"
:将密码设置为123
auth 123
:使用如ping命令之间需要先登录
RDB(Redis DataBase):在指定的时间间隔内将内存中的数据集快照写入磁盘, 恢复时将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中主进程不进行任何IO操作,这就确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后数据可能丢失。
fork的作用是复制一个与当前进程一样的进程,新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一样,但是是一个全新的进程,并作为原进程的子进程。
snapshotting
配置save
:只管保存,其他不管,全部阻塞bgsave
:Redis会在后台一部进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave
命令获取最后一次成功执行快照的时间flushall
命令,也会产生dump.rdb文件,但里面是空的,无意义redis-check-rdb --fix dump.rdb
命令用来修复dump.rdb文件动态所有停止RDB保存规则的方法:redis-cli config set save ""
,或者在配置文件中将save设为空
优势: 适合大规模的数据恢复,对数据完整性和一致性要求不高
劣势:在一定时间间隔做一次备份,所有如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。fork的时候,内存中的数据被克隆了一份,大致2北大的膨胀性需要考虑。
AOF(Append Only File):以日志的形式来记录每个写操作,将Redis执行过的所有写智力高记录下来(读操作不记录),只许追加文件但不可以更改文件,Redis启动之初会读取该文件重构数据,换言之,Redis重启的话就根据日志文件价格写指令从前到后执行一次以完成数据的恢复工作
appendonly.aof和dump.rdb可以共存,但先加载前者,当前者不存在或有问题时再加载后者。建议RDB和AOF两种同时开启
中修改配置,将默认的
appendonly no`改为yesredis-check-aof --fix appendonly.aof
命令用来修复appendonly.aof文件AOF采用文件追加方式,文件会越来越大,为避免出现这种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
进行重写
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中的数据,每条记录有一条的set语句。重写AOF文件的操作,并没有读取旧的AOF文件,而是将整个内存中国的数据库内容用命令的方式重写了一个新的AOF文件,这点和快照有些类似。
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次重写后大小的一倍且文件大约64MB时触发。
优势:可以每秒同步、每修改同步和不同步。
劣势:相同数据集的数据而言AOF文件会远大于RDB文件,恢复速度慢于RDB。AOF运行效率要慢于RDB,每秒同步策略效率较好,不同步效率和RDB相同。
一次可以执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不允许加塞。
discard
:取消事务,放弃执行事务块内的所有命令
exec
:执行所有事务块内的命令,在此之前只是入队但没执行
multi
:标记一个事务块的开始,在此之后的命令只是入队但没执行
unwatch
:取消watch命令对所有key的监视
watch key1 [key2...]
:监视一个或多个key,如果在事务执行之前这些key被其他命令(非本事务的命令)所改动,那么事务将被打断。watch命令在multi命令之前,类似于乐观锁
正常执行:exec:执行所有事务块内的命令,在此之前只是入队但没执行
放弃事务:discard:取消事务,放弃执行事务块内的所有命令
全体连坐:如果中间有一条命令出错,则全部不执行。当在exec前就报error时会出现该情况
冤头债主:如果中间有一条命令出错,只有出错的命令不执行。当在exec前没有报error时会出现该情况,如对一个字符串加1
是进程间的一种消息通信模式,发送者(pub)发送消息,订阅者(sub)接受消息。
命令
psubscribe pattern1 [pattern2...]
:订阅一个或多个符合给定模式的频道,模式类似于正则表达式pubsub subcommand [argument1 [argument2...]]
:查看订阅与发布系统状态publish channel message
:将消息发送到指定频道punsubscribe [pattern1 [pattern2...]]
:退订所有给定模式的频道subscribe channel1 [channel2...]
:订阅给定的一个或多个频道的信息unsubscribe [channel1 [channel2...]]
:退订给定的频道subscribe c1 c2 c3 publish c2 hello-redis
主机数据更新后根据配置和策略,自动同步到备机的master/slave机制,master以写为主,slave以读为主。主要用于读写分离和容灾恢复。
slaveof 主库ip 主库端口
slaveof 主库ip 主库端口
命令。此时从机和主机数据完全一样。可以用info replication
命令查看当前Redis的属性,是从机还是主机。从机只能读不能写。当主机关机后,从机不会替代主机,还是从机。当主机恢复后,从机会自动和主机保持一致。从机关机后,再开机不会自动与主机连接,除非在配置文件中进行了相关配置。slaveof no one
命令指定新的主机,并对其他从机重新绑定新的主机从机启动成功连接到主机后会发送一个sync命令。主机借到命令后启动后台的存盘进程,同时手机所有接受到的用于修改数据集命令,在后台进程执行完毕后,主机将传送整个文件到从机,以完成一次完全同步。全量复制:而从机服务在接收到数据库文件数据后,将其存盘并加载到内存中。增量复制:主机继续将新的所有收集到的修改命令依次传给从机,完成同步。但是只要是重新连接主机,一次完全同步(全量复制)将被自动执行
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转化为主库
sentinel monitor 被监控数据库名(自己起名字) 127.0.0.1 6379 1
info replication
查看由于所有的写操作都是先在主机上操作,然后同步到从机上,所以从主机同步到从机有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,从机数量的增加也会使这个问题更加严重