常见三类存储系统
- RDBMS:关系型数据库系统
Oracle、DB2、PostgreSQL、MySQL、SQL Server...
- NoSQL:非关系型数据库,又包含四种流派
键值存储
Memcache、Redis
列式存储
Hbase、Cassandra
文档存储
MongoDB
图式存储
Neo4j
- NewSQL:本身在设计上就支持分布式的关系行数据库系统
Aerospike、FoundationDB、RethinkDB...
redis特性
既是一个缓存又是一个存储
in-memory:所有工作都在内存中实现,在磁盘上存储的主要目的是为了冗余
支持持久化存储
基于快照方式:数据异步传输,从内存中传输到磁盘上并保存起来
AOF:把每一次的写操作都直接附加在一个文件后面实现数据存储
支持主从的高可用:借助sentinel实现一定意义上的HA
支持分布式集群:读写操作可以在多借点进行
数据结构服务器:支持存储:字符串、列表、哈希(映射)、集合、有序集合等等
单线程:核心模块是单线程,这样的设计可以避免同步代码阻塞主线程,从而提高性能
支持消息队列,支持发布订阅特性
评估数据:
100W个较小键值需要消耗100M内存
在常见的linux之上支持大约50W的并发
Redis与memcached比较
redis组成:
redis-server
redis-cli:客户端一般不用,通常调用API来实现请求
redis-benchmark:压测工具
redis-check-dump & redis-check-aof:检查redis的两种持久化后的文件是否存在错误
安装配置redis
安装:yum -y install redis
启动redis
service redis start
或 redis-server --help 查看命令帮助
配置文件: vim /etc/redis.conf
daemonize no #是否为守护进程默认为no,即便为no但是基于脚本启动时依然运行为守护进程
port 6379 #默认端口
tcp-backlog 511 #定义 tcp等待队列的长度为511。redis的并发性很高,但是前端的并发访问量非常大并且接收缓冲都满掉了就会额外在找一个地方把新进来的请求暂存下来这个位置就叫backlog,tcp协议通常都会有backlog
bind 127.0.0.1 #监听地址
# unixsocket /tmp/redis.sock #定义socket文件位置,如果客户端和redis在同一台主机上建议像mysql一样打开socket。基于socket的客户端和服务端通信,在内存中直接交换数据,不再经过tcp/ip协议栈进行封装再重新拆封
# unixsocketperm 700 #和socket文件的访问权限
timeout 0 #客户端连接空闲多长时间后超时,0表示禁用此功能
tcp-keepalive 300 # TCP keepalive和HTTP keepalive
loglevel notice # 日志级别
logfile /var/log/redis/redis.log
# syslog-enabled no #基于syslog来记录
databases 16 #database表示redis内部的集合,表示可以用多少的database
(快照存储)
# save <seconds> <changes> #配置方法,每隔多少秒如果发生多大变化就进行存储
# save "" #表示禁用使用快照做持久化
示例:save 60 10000 #每隔60秒,有超过10000个键发生变化就做一次快照
stop-writes-on-bgsave-error yes #在进行bgsave(异步快照)时发生错误是否停止备份
rdbcompression yes #rdb文件是否执行压缩
rdbchecksum yes #是否对rdb的镜像文件做校验码检测
dbfilename dump.rdb #rdb文件名
dir /var/lib/redis #rdb文件保存位置
(主从配置)
# slaveof <masterip> <masterport> #启用此项是从服务器,指定主服务器ip和端口
slave-read-only yes #从服务器只读
(限制)
# maxclients 10000 #指明最大的客户端并发数
# maxmemory <bytes> #指定最多使用内存
(AOF持久化存储)
appendonly no #是否启用AOF
appendfilename "appendonly.aof" #AOF文件保存位置
# appendfsync always #每次执行完写操作都通知内核往磁盘同步一次
appendfsync everysec #每秒通知内核往磁盘同步一次
# appendfsync no #由内核自定决定
no-appendfsync-on-rewrite no #做重写AOF时,对新写的操作不做同步而暂存到缓存中
auto-aof-rewrite-percentage 100 #当前的AOF文件是上次重写时的二倍会自动触发一次重写操作
auto-aof-rewrite-min-size 64mb #最小重新大小为64M
客户端命令用法
# redis-cli #不指定参数表示连接到本地
Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
-h <hostname> #指定远程主机地址
-p <port>
-s <socket> #本地连接
-a <password>
-r <repeat> #执行n次命令
-i <interval> #每个命令执行完等待一段时间
redis交互式命令用法
help #获取帮助
help @<group> #因为redis支持众多数据结构,所以可以指定获取某一种数据结构所支持的操作
例: help @STRING #字符串所支持的操作
help <command> #查询命令帮助
help <tab> #可以用tab键自动填充命令
SELECT int #指定打开几号名称空间(数据库),一共可以有16个,默认为0号名称空间。
注意:同一个名称空间下键名是不允许重复的
String 结构常用命令(help @string)
SET key value [EX seconds] [NX|XX] #添加键值对或修改键值
#EX seconds 为设置过期时间
#NX 键不存在时才会执行
#XX 键存在时才会执行
例:set shop_a pingpang NX
GET key #获取键值
例:get shop_a
APPEND key value #附加字符串
例:APPEND shop_a qiu
STRLEN key #获取键值长度
INCR key #整数型键值加一
DECR key #整数型键值减一
例:
set count 0
INCR count
DECR count
SETEX key seconds value #设置过期时间
list 结构常用命令(help @list)
LINDEX key index #获取索引
LSET key index value #修改列表中指定的索引的值
RPUSH #从列表右边塞入一个元素,也可以定义一个新列表
LPUSH #从列表左边塞入一个元素,也可以定义一个新列表
RPUSH #如果没有相同的值则从列表右边塞入一个元素
LPUSHX #如果没有相同的值则从列表左边塞入一个元素
LPOP #从列表左边弹出一个元素
RPOP #从列表右边弹出一个元素
LLEN key #获取指定列表长度
- 示例
LPUSH list1 a b c fsd awc #定义一个列表
LINDEX list1 6 #获取列表中第7个值
set(集合) 结构常用命令(help @set)
SADD key member [member ...] #定义集合或向集合里添加元素
SISMEMBER key member #判断指定的值是否是集群元素
SINTER key [key ...] #多个集合交集运算
SUNION key [key ...] #多个集合并集运算
SCARD key #获取集合的元素的个数
SDIFFSTORE destination key [key ...] #多个集合差集运算并保存在一个键中
SINTERSTORE destination key [key ...] #多个集合交集运算并存储到一个键中
SUNIONSTORE destination key [key ...] #多个集合并集运算并存储到一个键中
SPOP key [count] #随机弹出一个或几个元素
SRANDMEMBER key [count] #随机获取一个或多个元素
SREM key member [member ...] #从集合中删除一个或多个元素
SSCAN key cursor [MATCH pattern] [COUNT count] #遍历集群中的元素
SSCAN set1 0 #表示变量所有
sorted_set(有序集合) 结构常用命令(help @sorted_set)
ZADD key [NX|XX] [CH] [INCR] score member [score member ...] #定义有序集合或添加集合元素
ZCARD key #获取个数
ZCOUNT key min max #获取指定范围内的元素个数
ZRANGE key start stop [WITHSCORES] #获取指定范围内的元素
ZRANK key member #查询指定元素的索引
ZREM key member [member ...] #删除一个或多个元素
ZSCORE key member #获取指定元素位于集合的第几个从1开始计算
ZSCAN key cursor [MATCH pattern] [COUNT count] #变量集群
例:ZSCAN sort_set 0 变量集群所有元素
hash(映射,类似于字典) 结构常用命令(help @hash)
HSET key field value #定义和添加hash元素
HSETNX key field value #只有不存在时才会设定
HDEL key field [field ...] #删除一个或多个元素
HGET key field #获取指定键值
HSCAN key cursor [MATCH pattern] [COUNT count] #基于游标方式遍历hash中的每一个值
HKEYS key #获取所有键列表
HVALS key #获取所有值列表
适合全体类型的命令
EXISTS key [key ...] #判断键是否存在
DEL key [key ...] #删除一个键
TYPE key #返回值的类型
KEYS pattern #满足给定pattern 的所有key
RENAME key newkey #重命名key
EXPIRE key seconds #设置一个key的生存时间
TTL key #获得一个key的生存时间
MOVE key db #将当前数据库的key转移到有dbindex索引的数据库
redis 连接相关命令(help @connection)
AUTH #认证相关
PING #测试服务器是否在线
ECHO message #打印
QUIT
SELECT
服务器端相关命令(help @server)
BGSAVE #异步将数据集同步到磁盘,需要启动快照功能,不会阻塞操作
SAVE #再主线程中同步保存快照,再主线程保存完成之前所有操作都会被阻塞
LASTSAVE #获取最近一次数据保存到磁盘的时间戳
CLIENT GETNAME #获取当前客户端的连接名
CLIENT KILL [ip:port] [ID client-id] #关闭指定连接
CLIENT SETNAME connection-name #设置当前连接名
CONFIG SET parameter value #运行时直接修改配置参数,只在当前生效不会保存到配置文件中
CONFIG GET parameter #获取当前配置参数值
CONFIG REWRITE #把内存中修改的配置参数同步到配置文件中
INFO [section] #获取当前服务器状态统计数据
CONFIG RESETSTAT #重置INFO 信息
DBSIZE #获取当前数据库中键的数量
FLUSHDB #删除当前选择数据库的所有key
FLUSHALL #清空数据库
MONITOR #实时监控访问redis的请求
SHUTDOWN [NOSAVE|SAVE] #关闭redis,并设置是否做安全的数据同步
SLAVEOF host port #配置主从
SLOWLOG subcommand [argument] #显示redis慢查询日志,需要开启慢查询日志功能
TIME #返回当前时间
SYNC #复制的内建命令
认证机制(默认只要是bind配置的IP中任何人都可以访问)
配置访问密码
vim /etc/redis.conf
requirepass 123456 #搜索requirepass 在下行添加上:requirepass 密码
service redis restart #重启redis
redis-cli #登录到redis交互页面
AUTH 123456 #进行认证
redis事务
redis事务:将多个命令进行打包一次性进行执行,在这个事务执行完之前其他的命令都会被阻塞
注意:redis事务不支持回滚
MULTI #开始一个事务,并把执行命令放在队列中
EXEC #当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行,并且服务器遍历客户端的事务队列,执行队列中保存的所有命令,最后将执行结果全部返回给客户端
WATCH #乐观锁,他可以在EXEC命令执行之前监视指定任意数量的数据库键,并且在EXEC命令执行时检查被监视的键是否有被其他客户端修改,如果是服务将拒绝执行事务并向客户端返回事务执行失败的结果
示例:
[root@cj ~]# redis-cli
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET IP 172.0.0.1
QUEUED
127.0.0.1:6379> GET IP
QUEUED
127.0.0.1:6379> SET NAME XIAOMING
QUEUED
127.0.0.1:6379> GET NAME
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "172.0.0.1"
3) OK
4) "XIAOMING"
127.0.0.1:6379>
redis 的发布与订阅功能
SUBSCRIBE channel [channel ...] #订阅一个或多个频道
PSUBSCRIBE pattern [pattern ...] #基于正则表达式模式订阅频道
PUBLISH channel message #向某个频道发消息
UNSUBSCRIBE [channel [channel ...]] #退订一个或多个频道
PUNSUBSCRIBE [pattern [pattern ...]] #基于模式匹配退订频道
redis的持久化
注意:持久不能取代数据备份,对redis数据库定期进行备份
RDB
RDB:快照机制,保存的数据是二进制格式。按照事先定制的策略,周期性的将数据保存至磁盘,数据文件默认为dump.rdb。此持久化方法是每次同步一次内存中所有的数据而不是增量的方式所以比较占用IO
工作模式:redis会创建一个子进程负责将内存中的内容快照到磁盘临时文件上去,父进程继续处理其他redis操作,当操作完成临时文件会替换旧dump.rdb 文件。不足之处是当rendis异常恢复的数据是快照时间的数据,最新一部分数据会丢失。
AOF
AOF:将redis每一次操作命令都以附加的方式直接附加到指定文件的尾部,当redis重启时可以通过重新执行文件中的命令在内存中重建数据库。可以实时进行持久话,但是文件会变得越来越大,例如重复执行一万次某一个操作但真正生效的是最后一个也会把这一万次记录保存下来
BGREWRITEAOF #完成AOF文件的重写。这种重写不会重读旧的AOF文件,重写时会创建一个子进程通过直接重读内存中的数据,为内存中所有数据生成一个命令集。所以它是类似于快照的操作将内存中的数据以命令的方式保存到临时文件中完成后去替换原来的AOF文件,所以AOF文件可以通过重写变小
主从复制
特点:
一个master可以有多个slave,slave也可以有slave
master以非阻塞方式将数据同步至slave:可以同时处理数据和同步多个slave
过程:
启动一个slave后,slave会向master发送请求同步主库上的数据。matser此时会启动一个子进程将内存数据快照保存到磁盘的数据文件中,并把数据文件发送给slave。slave收到后把数据文件保存到本地磁盘后从磁盘重载到内存中完成同步
注意:如果主服务器开启认证功能,从服务器需要使用masterauth <PASSWORD> 来连入服务请求使用此密码进行认证
配置从服务器命令:
SLAVEOF host port #指定主服务器IP和端口
配置文件:
# slaveof <masterip> <masterport> #配置启用从服务器
slave-serve-stale-data yes #主服务器异常,从服务器数据是否还可以继续被读取
slave-read-only yes #从服务器是否只读
repl-diskless-sync no #是否基于diskless机制同步,适用于磁盘慢带宽大的场景
repl-diskless-sync-delay 5 #延迟时间多少秒
repl-disable-tcp-nodelay no #是否启用tcp-nodelay 功能
slave-priority 100 #指明slave的优先级
# min-slaves-to-write 3 #如果从节点小于3个则禁止主服务器在接受写请求
# min-slaves-max-lag 10 #同步时间差不能小于10秒钟以上,否则主服务器拒绝写入
sentinel(哨兵模式)实现高可用
- 作用:
监控多个服务器节点是否异常
故障转移:如果检测到主服务器异常自动挑选一个从服务器作为主。并告知其他从服务器
sentinel本身是一个分布式系统,例如三个sentinel节点在发现主redis故障时互相确认是否都访问不到主redis。防止单节点sentinel发生故障
- 安装:
redis-sentinel就是一个有着特殊代码的redis,启动redis时使用参数:./redis-server /etc/sentinel.conf --sentinel 就相当于启动一个sentinel
- 启动步骤:
(1)运行redis-server中专用于 sentinel的功能代码
(2)初始化sentinel状态,根据指定的配置文件初始化监控的matser服务器列表
(3)创建向master的连接
- 配置文件 :/etc/redis-sentinel.conf
port 26379
logfile /var/log/redis/sentinel.log
sentinel monitor mymaster 127.0.0.1 6379 2 #指定matser的主机名(可以自定义)、IP、端口、法定票数(每个sentinel 节点可以有一票),默认最少2票才能执行操作。
sentinel down-after-milliseconds mymaster 30000 #master连接失败多少毫秒之后才认为是离线
sentinel parallel-syncs mymaster 1 #在执行故障转移时最多可以有多少个从服务器对新服务器进行同步
sentinel failover-timeout mymaster 180000 #故障转移的超时时间单位毫秒
- 命令:
SENTINEL masters #获取所有所监视的主节点对应配置的详细信息
SENTINEL slaves masterName #获取指定master的从服务器详细信息
SENTINEL get-master-addr-by-name <master name> 根据master名字获取IP地址;或者根据地址获取名字
SENTINEL reset #重置服务器所有状态
SENTINEL failover <master name> #手动执行故障转移
- Clustering
去中心化分布式数据库,通过分片机制进行数据分布,每个节点仅持有数据库的一部分数据