NoSql-redis
2020-11-20 14:24:14 1 举报
AI智能生成
redis
作者其他创作
大纲/内容
NoSql 入门和概述
入门概述
互联网时代背景下大机遇,为什么用NoSql
单机 MYSQL 的美好年代
Memcached(缓存)+Mysql+垂直拆分
mysql 主从复制读写分离
分库分表+水平拆分+mysql集群
mysql的扩展瓶颈
为什么使用NoSql
是什么(NoSql -> Not Only Sql:意思是: 不仅仅是Sql)
泛指 非关系型的数据库,这些类型存储不需要固定的模式,无需多余操作就可以横向扩展
能干嘛
易扩展
NoSql 数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特点
数据之间无关系,这样就非常容易扩展,也无形之间,在架构的层面上带来了可扩展性
大数据量和高性能
NoSql 数据库都具有非常高的读写性能,尤其在大数据量下,同样优秀,这就得益于它的无关系性,数据库的结构简单
一般mysql 使用 query cache ,每次表的更新cache 就会失效 是一种大粒度的 cache
在针对 web2.0 的交互频繁的引用,cache 性能不高,而 NoSql 的 cache 是记录级的
是一种细粒度的 cache ,索引 NoSql 在这个22层面上来说就要性能提高很多了
redis 1s 写 8w 读11w次
多样灵活的数据模型
NoSql 无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。
而在关系型数据库里 增删 字段是一件非常麻烦的事情
如果非常大数据量的表,增加字段简直就是一个噩梦
传统 RDBMS VS NoSql
RDBMS
高度组织结构化数据
结构化查询语言 (sql)
数据和关系都存储在单独的表中
数据操纵语言,数据定义语言
严格的一致性
基础事务
NoSql
代表着不仅仅是sql
没有声明性查询语言
没有预定义的模式
键 - 值 对应 ,列存储 ,文档存储,图形存储
最终一致性,而非ACID属性
非结构化和不可预知的数据
CAP原理
高性能: 高可用和可伸缩性
去哪下
Redis
Memcache
Mongdb
怎么玩
KV
Cache
Persistene(持久化)
...
3V+3高
大数据时代的3V
海量 Volume(体积)
多样 Variety(种类)
实时 Velocity(高速)
互联网需求的3高
高并发
高性能
高可扩
横向扩展
栗子 1个人干不了 2个人来干(集群)
没有极限
纵向扩展
栗子 2G内存不够插4G ,4G不行插 8G
有极限
当下NoSQL的经典应用
当下应用是 sql 和 NoSql 一起使用的
阿里巴巴中文站商品信息是如何存放的
阿里巴巴网站首页 以女装包包 为栗子
与我们 reids相关的,多数据源多数据类型的存储问题
商品基本信息
名称,价格,出厂日期,生产厂商等
存储在关系型数据库 mysql(也不是我们使用的mysql)/oracle 目前淘宝在去O 化 (拿掉了Oracle)
商品描述,详情,评价信息(多文字类)
多文字信息描述类,IO读写性能变差
存储在文档数据库 MongDB 中
商品图片
商品图片展现类
分布式的文件系统中
淘宝自己的TFS
Google 的GFS
Hadoop 的HDFS
商品的关键字(搜索框里面的文字)
搜索引擎,淘宝内用
ISearch
商品的波段性的热点高频信息
内存数据库
Tair , Redis , Mencache
商品的交易,价格计算,积分累计
外部系统,外部第三方支付接口
支付宝
总结大型互联网应用 (大数据,高并发,多样数据类型)的难点和解决方案
难点
数据类型多样性
数据源多样性和变化重构
数据源改造而数据数据服务平台不需要大面积重构
解决方案
阿里,淘宝干了什么 UDSL
UDSL是什么?
统一数据服务层 UDSL ,在网站应用集群和底层数据源之间,构建一层代理,统一数据层
什么样?
映射
API
热点缓存
...
NoSql数据模型简介
以一个点上客户,订单,订购,地址模型来对比以下关系型数据库和非关系型数据库
传统的关系型数据库你如何设计呢?
ER图 (1:1/1:N/N:N 主外键等常见)
NoSql 是如何设计的?
什么是BSON?
BSON 是一种类 json 的一种二进制形式的存储格式,简称 Binary Json , 它和 Json 一样,支持内嵌的文档对象和数组对象
NoSql 模型为
俩着对比,问题和难点
为什么NoSql 情况可以用聚合模型来处理
高并发的操作是不太建议有关联查询的,互联网公司用冗余数据来避免关联查询
分布式事务是支持不了太多的并发
想想关系型数据库是如何查的?
如果使用BSON 这样查询是不是很简单少了很多的left join
聚合模型
KV键值对
BSON
列族
是按列存储数据的,最大的特点是 方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势
图形
NoSql 数据库的四大分类
KV键值
新浪 Berkeley + redis
美团 redis + tair
阿里,百度 memcache + redis
文档型数据库(bson 格式比较多)
CouchDB
MongoDB
是一个基于分布式文件存储的数据库,由C++语言编写,旨在web应用提供可扩展的高性能数据存储解决方案
MongoDB 是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库中当中功能最丰富,最像关系数据库的
列存储数据库
Cassandra , HBase
分布式文件系统
图关系数据库
它不是放图形的,放的是关系比如 : 朋友圈社交网络,广告推荐系统,社交网络,推荐系统等,专注于构建关系图谱
Neo4j , InfoGrid
四者对比
子主题
在分布式数据库中CAP原理 CAP +BASE
传统的ACID是什么
原子性
隔离性
持久性
一致性
CAP
C: Consisteny 强一致性
A: Availabilty 可用性
P: Partition tolerance 分区容错性
CAP 的3进2
CAP: 核心是 一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能满足2 个
CA(传统Oracle/mysql数据库)
单点集群,满足一致性,可用性系统,通常在可扩展性上不太强
CP(Redis、Mongodb)
满足一致性,分区容错性的系统,通常性能不是特别高
AP(大多数网站架构的选择)
满足可用性,分区容错性,通常可能对一致性要求低一些
BASE
什么是 base ?
base 就是为了解决关系数据库强一致性引起的可用性降低而提出的解决方案
basically available -基本可用
soft state - 软状态
eventually consistent -最终一致
它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观,为什么这么说呢? 缘由就在于大型系统往往由于地域分布和极高性能的要求,不可能采用分布式事务来完成这些指标,要想获得这些指标,我们必须采取另外一种方式来完成,这里 Base 就是解决办法
分布式+集群简介
分布式
不同的多态服务器上面部署不同的服务模块(工程),它们之间通过 RPC/RMI 通信和调用,对外提供服务和组内协作
集群
不同的多态服务器上面部署相同的服务模块(工程),通过分布式调度软件进行统一的调度,对外提供服务和访问
问题
当客户端 通过负载均衡 访问多台服务器的时候, session 放在那里??
1),放在 客户端的 cookie 里
缺点 不安全,网络负担效率低
2), 放在 独立的文件服务器/mysql数据库
缺点: 有大量的io效率问题
3), 服务器之间 session复制
缺点: session 数据冗余,服务器节点越多浪费越大
4),存储在Nosql缓存数据库中,解决io压力
优点: 完全存储在 内存中,速度快,数据结构简单
Redis入门介绍
入门概览
是什么?
redis : REmote DIctionary Server (远程字典服务器)
redis 与其它 k/v缓存产品有以下3个特点
redis 支持数据的持久化,可以将内存中的数据保持到磁盘中,重启的时候可以再次加载进行使用
redis 不仅仅支持简单的k-v类型的数据,同时还支持 list,set,zset,hash等数据结构进行存储
redis 支持数据的备份,即 master-slave 模式的数据备份
redis 和 memcache 区别
持久化
redis 支持持久化 memcache不支持持久化
数据类型
memcache 只支持string类型
redis 支持 list,set,zset,hash,string
架构
redis 单线程+多路IO复用
memcache 多线程+锁
能干嘛?
内存的存储和持久化,redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务取最新的N个数据的操作
如: 可以将最新的10条评论的ID放到 redis的list集合里面模拟类似于 httpsession 这种需要设定过期时间的功能
发布,订阅消息系统
定时器,计算器
去哪下?
http://www.redis.cn/
怎么玩?
数据类型,基本操作和配置
持久化和赋值,RDB/AOF
事务的控制
复制
...
Redis-Linux 安装
运行 make命令的时候出现 /bin/sh: cc: 未找到命令
安装gcc
yum install gcc-c++ -y
二次运行make 出现 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
运行 make distclean 然后在执行 make
继续执行出现 错误:‘struct redisServer’没有名为‘server_cpulist’的成员
1、安装gcc套装:
yum install cpp
yum install binutils
yum install glibc
yum install glibc-kernheaders
yum install glibc-common
yum install glibc-devel
yum install gcc
yum install make
2、升级gcc
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
3、执行完上述命令后再次make即可。
yum install cpp
yum install binutils
yum install glibc
yum install glibc-kernheaders
yum install glibc-common
yum install glibc-devel
yum install gcc
yum install make
2、升级gcc
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
3、执行完上述命令后再次make即可。
Hint: It's a good idea to run 'make test' ;) 编译成功
执行 make install 安装
Redis启动后杂项基础知识讲解
单进程
单进程模型来处理客户端的请求,对读写等事件的响应是通过对 Epoll 函数的包装来做到的,Redis 的实际处理速度依靠主进程的执行效率
Epoll 是Linux 内核为处理大批量文件描述符而做了改进的 epoll ,是Linux 下多路复用 IO 接口 select/poll 的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
默认16个数据库,类似于数组的下标从 零 开始,,初始默认使用零号库 (在 redis.conf 配置文件中可以看出)
Select 命令切换数据库
Dbsize 查看当前数据库的key数量
flushall 通杀全部数据库
flushdb 清空当前数据库
统一密码管理 ,16个库都是同样的密码,要么都能连上要么都连不上
redis 的索引是从零开始的
为什么默认端口是 6379
Redis 数据类型
Redis 五大数据类型
String 字符串
String 是 Redis 最基本的类型,与Memcached 一模一样的类型,一个key对应一个value,是二进制安全的(意思是redis的string可以包含任何数据,比如jpg或者序列化对象等)
Hash 哈希类似于Java里的Map
是一个键值对集合,是一个String类型的field 和 value 的映射表,hash特别适合用于存储对象(类似于java 的Map<String,Object>)
List 列表
是一个简单的字符串列表,按照插入顺序排序,可以在头部和尾部插入一个元素,底层是链表
Set 集合
是String类型的无序集合,它是通过hashtable实现的
Zset (Sorted set 有序集合)
redis 的set 和zset 一样都是string类型元素的集合,且不允许重复的成员
不同的是zset每个元素都会关联一个double类型的分数
redis正是通过分数来为集合中的成员进行从小到大的排序, zset的成员是唯一的,但分数(score) 却可以重复
哪里去获取redis常见数据库类型操作命令
http://www.redis.cn/
Redis 键(key)
keys * --查看当前数据库所有k
exists k -- 判断当前数据库k是否存在1为存在0为不存在
move k 2 -- 把k移动到2号数据库
expire k 10 -- 为k设置过期时间10s
ttl k -- 查看还有多少秒过期 -1表示永不过期 -2 表示已过期
type k -- 查看k的数据类型
dbsize -- 查看数据库的key数量
flushdb -- 清空当前库
flushall -- 通杀全部库
Redis --- string
set / get /del / append / strlen
Incr (加)/ decr (减)/ Incrby /decrby (注意一定要是数字才能进行加减)
getrange
获取指定区间范围的值,类似于 betwenn ... and 的关系
setrange
设置覆盖key对应的string的一部分,从指定的offset处开始,覆盖value的长度。
setex
设置key在给定的seconds时间之后超时过期
setnx
将key设置值为value,如果key不存在,这种情况下等同SET命令。
mset / mget / msetnx
设置添加/获取/当所有key都不存在添加多个k - v
getset
设置一个key的val ,并获取设置前的值
Redis --- list
lpush / rpush(怎么进怎么出,其它都是逆反) /lrange
lpop / rpop
lindex --- 按照索引下标获取元素(按照左/右的下标)
llen --获取当前数据长度
lrem -- 从list集合中删除n个value
ltrim --截取指定范围后的值然后在赋值给key
rpoplpush -- 意思是从列表右侧 弹出一个 放入第二列表的左侧(rpop 和 lpush)
lset --设置 列表index 位置的value
linsert -- 把某个值插入在指定的值before / after
Redis --- set
sadd / smembers(查询集合全部元素)
sismember -- 判断一个给定的值是否是一个集合的成员
scard --获取集合中的元素个数
srem - 从集合中删除一个或者多个元素
srandmember -- 从集合中随机取出来几个元素
spop -- 随机出栈
smove k1 k2 -- 在 k1 里面某个值,赋值给k2
数学集合类
差集 sdiff(第一个有,第二个没有的)
交集 sinter
并集 sunion
Redis --- hash
KV模式不变 , 但V是一个键值对
hset / hget / hmset / hmget / hgetall /hdel
hlen -- 查看hash长度
hexists --判断 k 的字段是否存在
hkeys / hvals
hincrby / hincrbyfloat
hsetnx -- 设置hash的一个字段,当该字段不存在时生效
Redis --- zset(最复杂的数据类型)
在set的基础上,加了一个 score 值,之前set是 s1 v1 v2 v3 现在的zset是 s1 score v1 score v2 score v3
zadd / zrange
zrangebyscore --返回有序集合中,指定分数(score)间的成员,从底到高
zrem -- 从集合中删除一个或多个元素
zcard (统计集合的长度)/ zcount (指定min,max之间的个数)
zrank --确定在排序集合中的索引
zscore k v -- 根据v获取对应的分数 score
zrevrank --逆方向获取下标值
zrevrange --逆时针排序
zrevrangebyscore -- 逆时针根据分数排序 从高到低
解析配置文件 redis.conf
Units 单位
配置大小单位,开头只定义了一些基本的度量单位,只支持bytes ,不支持 bit
对大小写不敏感
INCLUDES
和我们的 Struts2 配置文件类似,可以通过 includes 包含 redis.conf 可以作为总闸,包含其它文件
GENERAL
daemonize no
pidfile "/var/run/redis_6379.pid"
# requirepass foobared
NETWORK
tcp-backlog 511
timeout 0
tcp-keepalive 300
loglevel notice
logfile ""
# syslog-enabled no
# syslog-ident redis
# syslog-facility local0
databases 16
SNAPSHOTTING (快照)
# save <seconds> <changes> : save 秒数 写操作次数
可以禁用save
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir ./
SECURITY (安全)
获取启动redis的目录
config get dir
重新设置redis 密码
config set requirepass "密码"
获取当前redis密码
config get requirepass
怎么在redis输入命令呢
auth "密码"
取消redis密码如何操作呢
config set requirepass ""
shutdown -> exit
重启redis 然后使其生效
CLIENTS 客户端限制
# maxclients 10000
MEMORY MANAGEMENT(内存管理限制)
# maxmemory <bytes>
# maxmemory-samples 5
# maxmemory-policy noeviction (默认永不过期)
redis memory 过期策略(当内存不足以容纳新写入数据时)
volatile-lru
使用LRU 算法移除key,只对设置了过期时间的键,移除最近最少使用的key。
allkeys-lru(常用)
使用LRU算法移除key,移除最近最少使用的key
volatile-lfu
在过期密集的键中,使用LFU算法进行删除key。
allkeys-lfu
使用LFU算法移除所有的key。
volatile-random
在过期集合中移除随机的key,只设置了过期时间的键
allkeys-random
移除随机的key
volatile-ttl
移除那些TTL 值最小的key,即那些最近要过期的key
noeviction
不进行移除,针对写操作,只是返回错误信息
APPEND ONLY MODE (追加一个方式)
appendonly no(默认是no ,yes就打开aof持久化)
appendfilename "appendonly.aof"
appendfsync everysec
no
依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差
always
同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性较好
everysec
出厂默认推荐,异步操作,每秒记录,如果一秒宕机,有数据丢失
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
REDIS CLUSTER (集群)
# cluster-enabled yes
# cluster-config-file nodes-6379.conf
# cluster-node-timeout 15000
# cluster-require-full-coverage yes
Redis 的持久化
总体介绍
rdb (Redis DataBase)--存储的数据
是什么?
在指定的时间间隔能对你的数据进行快照存储到磁盘
Redis 会单独创建 (fork) 一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件
整个过程中,主进程是不进行任何的IO操作的,这就确保了极高的性能,如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB 方式要比 AOF 方式更加高效,RDB 的缺点是最后一次持久化后的数据可能丢失。
Fork
在Linux程序中,fork() 会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux会引入一个写时复制技术
一般情况父进程和子进程会共用同一段物理内存,只有进程空间的隔断内容要发生变化时,才会将父进程的内容复制一份给子进程
rdb 保存的是 dump.rdb 文件
如何触发RDB快照
配置文件中默认的快照配置
冷拷贝后重新使用
可以 cp dump.rdb dump_bk.rdb
命令save 或者 bgsave
redis.conf 配置文件满足 save 的判断可以自动保存
save : save时只管保存,其它不管,全部阻塞
bgsave : Redis 会在后台异步进行快照操作,快照同时还可以响应客户端请求,可以通过 lastsave 命令来获取最后一次成功执行快照的时间
执行 flushall 命令也会产生 dump.rdb文件,但是里面是空的,无意义
如何恢复
将备份文件 (dump.rdb )移动到 redis 安装目录并启动服务即可
config get dir 获取redis安装目录
优势
适合大规模的数据恢复
对数据的完整性和一致性要求不高
劣势
在一定时间做一次备份,所以如果redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改
fork 的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
如何停止
动态停止 RDB 保存规则的方法 , redis-cli ,config set save ""
小总结
aof (Append Only File) --存储的指令
是什么?
以日志的形式来记录每个写操作, 将redis 执行过的所有写指令都记录下来(读操作不记录),只追加文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据
换言之,redis 重启的话就是根据日志文件的内容将指令从前到后执行一次以完成数据的恢复
aof 保存的是 appendonly.aof文件
文件位置
保存在 rdb 统一目录下即 dir 目录
aof 启动/修复 / 恢复
正常恢复
启动: 设置yes
将有数据的 aof 文件复制一份保存到对应目录 (config get dir)
恢复: 重启redis 然后重新加载
异常恢复
启动: 设置 yes
备份被写坏的aof 文件
修复: redis-check-aof --fix 文件名 ->进行修改
恢复: 重启redis 然后重新加载
Rewrite
是什么?
aof 采用文件追加方式,文件会越来越大为了避免出现这种情况,新增了重写机制,当 aof 文件的大小超过所设定的阈值时,redis会启动 aof 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令 bgrewriteaof
重写原理
aof 文件持续增长而过大时,会 fork 出一条新进程来将文件重写( 也是先写临时文件最后在 rename)
遍历 新进程的内存中数据,每条记录有一条Set 语句,重写 aof文件的操作,并没有读取旧的 aof 文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的 aof 文件,这点和快照有点类似
触发机制
Redis 会记录上次重写时aof 文件大小, 默认配置是当 aof 文件大小是上次 rewrite 后大小的一倍且文件大于 64M时触发
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb 可以看出
auto-aof-rewrite-min-size 64mb 可以看出
优势
每秒同步 appendfsync always
同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好
每修改同步 appendfsync everysec
异步操作,每秒记录,如果一秒内宕机,有数据丢失
不同步 appendfsync no
从不同步操作
劣势
相同的数据集的数据而言 aof 文件要远大于 rdb文件 恢复速度慢于rdb
aof 运行效率要慢于 rdb,每秒同步策略较好,不同步效率和rdb 相同
小总结
客户端 --命令请求--> 服务器 --网络协议格式的命令内容--> aof文件
总结 (Which one)
rdb 持久化方式能够在指定的时间间隔能对你的数据进行快照存储
aof 持久化方式能记录每次对服务器写的操作,当服务器重启的时候回重新执行这些命令来恢复原始数据,aof 命令以redis 协议追加保存每次写的操作到文件的末尾
redis 还能对aof文件进行后台重写,使得aof文件的体积不至于太大
只做缓存: 如果你只希望你的数据在服务器上运行的时候存在,你也可以不使用任何持久化方式
同时开启2中持久化方式
在这种情况下, 当redis 重启的时候回优先加载 aof文件来恢复原始的数据,因为通常情况下 aof 文件保存的数据集要比 rdb 文件保存的数据更完整
rdb 的数据不实时,同时使用两者服务器重启也只会找 aof文件 ,那要不要只使用aof 文件呢? 作者建议不要,因为 rdb 更适合用于备份数据库(aof 在不断变化不好备份) 快速重启,而且不会有 aof 可能潜在的 bug,留着作为一个万一的手段
性能建议
因为 rdb 文件只用作备用途,建议只在 Slave 上持久化 rdb 文件,而且只要 15 分钟备份一次就够了,值保留 save 900 1 这条规则
如果 enable aof 好处是 在最劣势情况下也只会丢失不超过2秒的数据,启动脚本较简单只load自己的aof文件就可以了,
如果不 enable aof,紧靠 master-slave replication 实现高可用也可以
Redis 的事务
是什么?
是一个单独的隔离操作,可以一次执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞
redis 事务的主要作用是 串联多个命令防止别的命令插队
redis的事务
能干嘛?
一个队列中,一次性,顺序性,排它性的执行一系列命令
怎么玩?
常用命令
Case1 : 正常执行
Case2 : 放弃事务
Case3 : 全体连坐
Case4 : 源头债主
Case5 : watch监控
悲观锁/乐观锁/CAS( check and set)
悲观锁
悲观锁(Pessimistic Lock) 顾名思义,就是很悲观,每次去拿数据都以为别人会修改,所以每次在拿数据的时候都会上锁,这样别人就想拿这个数据就会 block 直到它拿到锁,传递关系型数据库就用到了 这种锁机制,比如行锁,表锁等 读锁,写锁等,都是在操作之前先上锁
乐观锁
乐观锁(Optimistic Lock) 顾名思义,就是很乐观,每次去拿数据都认为别人不会修改,所以不会上锁,但是在更新的时候,会判断一下再次期间别人有没有去更新这个数据,可以使用版本号(version)等机制,乐观锁适用于多读的应用类型,这样可以提高吞吐量
CAS
初始化信用卡可用余额和欠额
无加塞篡改,先允许监控再开启 multi 保证两笔金额变动在同一事务内
有加塞篡改
unwatch
一旦执行了 exec 之前加的监控所都会被取消了
小结
watch 指令,类似乐观锁,事务提交时,如果key的值已经被别的客户端改变,比如某个list已经被别的客户端 push/pop 过了,整个事务队列都不会被执行
通过 watch 命令在事务执行之前监控了多个keys ,倘若在 watch 之后有任何key的值发生了变化,exec命令执行的事物都将被放弃,同时返回 Nullmulti-bulk 应答以通知调用者事务执行失败
阶段
开启 : multi开始一个事务
入队 : 将多个命令入队列到事务中,接到这列命令并不会立即执行,而是放到等待执行的事务队列里面
执行 :exec命令触发事务
特性
单独的隔离操作 : 事务中的所有命令都会序列化,按序列地执行,事务在执行的过程中,不会被其他客户端发送来的命令请求打断
没有隔离级别的概念 : 队列中的命令没有被提交之前都不会实际的被执行,因为事务提交前任何执行都不会被实际执行,也就不存在 事务内的查询要看到事务里的更新,在事务外查询不能看到这个让人万分头疼的问题
不保证原子性 : redis同一事务中如何有一条命令执行失败,其后的命令任然会被执行,没有回滚
ab工具模拟并发
安装
yum install httpd-tools
ab -n 请求数
ab -c 并发数
ab -p 指定请求数据文件
在 /home/myredis/创建profile文件
ab -T "application/x-www-form-urlencoded" 表示post请求
案例
get请求
ab -n 1000 -c 200 http://192.168.247.1:8080/spike/commodity?commodity=100
post请求
ab -n 1000 -c 200 -p /home/myredis/profile -T "application/x-www-form-urlencoded" http://192.168.247.1/spike/commodity
LUA脚本
LUA脚本在redis中的优势
1),将复杂的或者多步的redis操作,写为一个脚本,以此提交给redis执行,减少反复连接redis的次数,提升性能
2),Lua 脚本是类似redis事务,有一定的原子性,不会被其它命令插队,可以完成一些redis事务性的操作
3),但是注意redis的lua脚本功能,只有在 2.6版本以上才可以使用
Redis 的发布订阅(了解)
是什么?
进程间的一种消息通信模式,发送者(pub)发送消息,订阅着(sub)接受消息
订阅/发布消息图
命令
psubscribe
订阅一个或多个符合给定模式的频道
pubsub subcommand
查看订阅与发布系统的指定频道
publish
退订所有给定模式的频道
subscribe
订阅给定一个或多个频道
unsubscribe
指退订给定频道
案栗
设置消息接受者 psubscribe
设置消息的发送者 pusblish
Redis 的复制(master-slave)
是什么?
官方文档
行话 : 也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的 master / slaver 机制,Master 以写为主,Slave 以读为主
能干嘛?
容灾恢复
读写分离
怎么玩?
1), 配从(库)不配主(库)
2), 从库配置: slaveof 主库ip 主库端口
每次与 master 断开后,都需要重新连接,除非你配置进 redis.conf 文件
info replication
3),修改配置文件细节操作
拷贝多个 redis.conf 文件
开启 daemonize yes
pid 文件名称
指定端口 port
log 文件名字
dump名字.rdb
4),常用3招
一主二仆
init
一个master 俩个 slave
日志查看
主从问题演示
1),如果三个redis 主机和从机都执行 set k6 v6 是否可以都执行
主机可以(写操作)添加k6 ,从机没有权限来添加 k6会直接报错
2),如果主机 宕机了 从机是否上位或者 继续等待主机恢复
redis主机挂了,从机的数据还有,从机的角色还是 slave ,继续等待主机恢复
3),如果主机恢复了,从机是否照旧进行数据备份,还是从机数据乱了
主机恢复,主机添加新的数据,然后从机依旧获取最新的数据
4),从机死了,从机回来是 slave 还是master 如果是slave 能否续接上主机的数据
从机恢复后,通过 info replication 查看是 master ,如果想是从机需要使用 slave 主机 端口,连接上后,数据依然是主机的数据
5), 主机添加数据,从机是否能拿到主机的最新值
主机 set k值 ,从机可以拿到最新值
薪火相传
上一个 slave 可以是下一个slave 的Master ,slave 同样可以接受其他slaves 的连接和同步请求,那么该slave 作为链条中下一个的 master 可以有效减轻 master 的写压力
中途变更转向: 会清楚之前的数据,重新建立拷贝最新的
slaveof 新主库 ip 新主库端口
反客为主
slaveof no one
使当前数据库停止与其他数据库的同步,转成主数据库,然后形成一个新的中心点
复制原理
1), slave启动成功连接到master 后会发送一个sync命令
2), 主机立即进行存盘操作,发送 RDB文件给从机
3), 从机收到RDB文件后,进行全盘加载
4), 之后每次主机的写操作,都会立刻发送给从机,从机执行相同的命令
全量复制
而slave服务在接受到数据库文件数据后,将其存盘并加载到内存中
增量复制
master继续将新的所有手机到的修改命令依次传给slave,完成同步
但是只要是重新连接 master 一次完全同步(全量复制)将被自动执行
哨兵模式 ( sentinel)
是什么?
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
怎么玩
调整结构 ,6379带着 80,81
在自定义的 /home/myredis/目录下创建 sentinel.conf 文件,名字绝不能错
配置哨兵 sentinel 文件
seninel monitor 被监控主机数据库名字(自己给服务器起的名字) 127.0.0.1 6379 1
上面最后一个数子1 ,表示主机挂掉后 replica-priority 100
启动哨兵
redis-sentinel /home/myredis/sentinel.conf
问题
启动哨兵 ,如果81从机挂掉一个,不会影响主从复制
启动哨兵,如果主机6379挂掉了,哨兵会让俩个从机进行(石头剪刀布)谁赢谁就是新主机
如果6380成为了新主机,这时6379主机又恢复正常,这时6379就会变为一个6380的从机
一组 sentinel 能同时监控多个 master
复制的缺点
由于所有写的操作都是现在master 上操作,然后同步更新到 slave上,所以从 master 同步到 slave 上有一定的延迟,当系统很繁忙的时候,延迟问题会更严重,slave机器数量增加也会使这个问题更加严重
Redis 的集群
为什么要用集群?
容量不够,redis如何记性扩容?
并发写操作,redis如何分摊
是什么?
redis 集群实现了对redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在N个节点中,每个节点存储总数据的1/N
redis 集群通过分区 ( partition) 来提供一定程度的可用性 ( availability) : 即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求
怎么用
安装 ruby环境
yum install ruby
yum install rubygems
修改redis.conf配置文件
把集群注销掉的内容打开
同时打开6台redis的服务
打开后如下 ps -ef|grep redis
将6个节点合成一个集群
组合之前,请确保所有redis实例启动后, nodes-xxxx.conf文件是否正常生成
将集群合体 cd /opt/自己的redis目录/src
redis-cli --cluster create 192.168.247.110:6379 192.168.247.110:6380 192.168.247.110:6381 192.168.247.110:6389 192.168.247.110:6390 192.168.247.110:6391 --cluster-replicas 1
以集群的方式进入客户端
redis-cli -c -p 某一端口号
如何查看集群信息
cluster nodes
redis cluster如何分配这6个节点
1), 衣蛾集群至少要有三个子节点
2), 选项 -replicass 1 表示我们希望为集群中的每个主节点创建一个从节点
3), 分配原则尽量保证每个主数据库运行在不同的ip地址,每个从库和主库不在一个ip地址上
什么是 slots ?
1), 一个redis 集群包含了 16384个插槽( hash slot) ,数据库中的每个键都属于这16384个插槽的其中一个,集群使用公式 CRC16(key) % 16384 来计算key 属于那个槽,其中 CRC16(key) 语句用于计算键key 的CRC16效验和
2), 集群中的每个节点负责处理一部分插槽,举个栗子,如果一个集群可以有主节点,其中
节点A负责处理 0 - 5500 号插槽
节点B负责处理 5501-11000 号插槽
节点C负责处理 11001-16384 号插槽
在集群中录入值
1), 在 redis -cli 每次录入,查询键值,redis都会计算出该key 应该送往哪里的插槽,如果不是该客户端对应服务器的插槽,redis会报错,并告知前往的 redis实例地址和端口
2), redis -cli 客户端提供了 -c 参数实现自动重定向
如 redis -cli -c -p 6379 登录后,在录入,查询键值对可以实现自动重定向
3), 不在一个slot 下的键值,是不能使用 mget,mset 等多键值操作
4), 可以通过 {} 来定义组概念,从而使key 中{} 内相同内容的键值对放到一个slot中去
查询集群中的值
cluster keyslot xx
计算键key 应该被放置在那个槽上
cluster countkeysinslot xx
返回槽slot 目前包含的键值对数量
cluster getkeysinslot xx xx
返回count个slot槽中的键
故障恢复
1),如果主节点下线,从节点能够自动升为主节点?
从节点可以自动升级为主节点 master
2), 主节点恢复后,主从关系会如何?
主节点变为从服务器 slaver
3), 如果所有某一段插槽的主从节点都宕掉,redis服务是否还能继续?
如果主从服务都宕掉了,那么主从那些插槽之间,是无法使用的,其它没有坏掉的节点也无法使用
注意: redis.conf 中的参数 , cluster-require-full-coverage 只有当 16384个插槽都正常的使用才能对外进行服务
redis 集群好处
实现扩容
分摊压力(既能分担内存压力,也能分担读写压力)
无中心配置相对简单
redis 集群的不足
多键操作是不支持的,lua脚本不被支持
由于集群方案出现比较晚,很多公司已经采用了其他的集群方案,而代理或客户端端分片的方案想要迁移到 redis cluster 需要整体迁移,不是逐步过渡,复杂度较高
如何取消redis集群
1),kill -9 pid //依次关闭所有Redis节点进程
2), 2.删除集群相关文件
Redis 的java的JedisCluster
0 条评论
下一页