NoSQL
CAP:Consistency(强一致性), Availability(高可用性), Partition Tolerance(分布式容忍性)(只能三进二)
RDBMS:CA(传统关系型数据库)
MongoDB,HBase,Redis:CP
CouchDB,Cassandra,DynamoDB:AP
NOSQL里分布式容忍性(P)是必须实现的
AP大多数网站架构的选择
BASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案。
BASE其实就是下面三个术语的缩写:
基本可用(Basically Available)
软状态(Soft state)
最终一致(Eventally consistent)
分布式:不同的多台服务器上面部署不同的服务模块(工程),他们之间通过RPC/Rmi之间的通信和调用,对外提供服务和组内协作。
集群:不同的多台服务器上面部署相同的服务模块,通过分布式调度软件进行统一的调度,对外提供服务和访问。
Redis:分布式内存数据库,写80000/s 读110000/s
Redis三个特点:
1.支持数据持久化;
2.不仅支持简单的key-value类型数据,同时还提供list,set,zset,hash等数据结构的存储。
3.支持数据的备份,即master-slave数据模式的数据备份;
Redis:单进程,单进程模型来处理客户端的请求。对读写等事件的响应是通过对epoll函数的包装来做到的。Redis的实际处理速度完全依靠主进程的执行效率。
默认是16个数据库,类似数组下标从零开始,初始默认使用零号库。
select命令切换数据库。
Dbsize查看当前数据库的key的数量。
Flushdb:清空当前库
Flushall:通杀全部库
统一密码管理,16个库都是同样密码,要么都OK要么一个个也连接不上。
Redis索引都是从零开始
为什么默认端口是6379
Redis的五大数据类型:
String(字符串)
Hash:(哈希,类似java里的Map)
List(列表)
Set(集合)
Zset(sorted set:有序集合)
String(字符串):
String是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value
String类型是二进制安全的。意思是redis的String可以包含任何数据。比如jpg图片或者序列化的对象。
string类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M
Hash(哈希)
Redis hash是一个键值对的集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
类似Java里面的Map(String,Object)
List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个链表。
Set(集合)
Redis的Set是string类型的无序集合。它是通过Hashtable实现的。
Zset(sorted set:有序集合)
Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。
redis正是通过分数来为集合中的成员进行大小排序。zset的成员是唯一的,但分数却可以重复。
key关键字
keys *
exists key的名字,判断某个key是否存在。
move key db -->当前库就没有了,被移除了
expire key秒钟:为给定的key设置过期时间。
ttl key:查看还有多少秒过期,-1表示永不过期,-2表示已过期
type key查看你的key是什么类型
DEL key:删除key
Redis字符串(string)
单值单value
set/get/del/append/strlen
Incr/decr/incrby/decrby,一定要是数字才能进行加减
getrange/setrange
setex(set with expire)键秒值/setnx(set if not exists)
mset/mget/msetnx (一次操作多个数字)
getset(先get再set)
Redis列表(list):单值多value
lpush/rpush/lrange:r先进先出
lpop/rpop:lpop栈顶先出
lindex,按照索引下标获得元素(从上到下)
llen:长度
lrem key:删除N个value, 删除N个value:LREM list03 2 3
ltrim key:开始index 结束index,截取指定范围的值后再赋值给key
rpoplpush 源列表 目的列表:源栈底压到栈顶
lset key index value
linsert key before/after 值1,值2
总结:
list是一个字符串链表,left,right都可以插入添加;
如果键不存在,创建新的链表;
如果值已存在,新增内容;
如果值全移除,对应的键也就消失了。
链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。
Redis集合(Set):单值多value
sadd/smembers/slsmember
scard,获取集合里面的元素个数
srem key value 删除集合中元素
srandmember key 某个整数(随机出几个数)
spop key随机出栈
smove key1 key2 在key1里某个值 作用是将key1里某个值赋给key2
数学集合类:差集:sdiff 交集:sinter 并集:sunion
Redis哈希(Hash)很重要
kv模式不变,但value是一个键值对(hset user id 11, hget user id,可以存对象)
hset/hget/hmset/hmget/hgetall/hdel
hlen
hexists key 在key里面的某个值的key
hkeys/hvals(得到key和value)
hincrby/hincrbyfloat(增加)
hsetnx
Redis集合Zset(sorted set)
在set基础上,加上一个score值。
之前set是k1 v1 v2 v3
现在zset是k1 score1 v1 score2 v2
zadd/zrange(zadd zset01 60 v1 70 v2 80 v3 90 v4 100 v5)(zrange zset01 0 -1)(只带值)(zrange zset01 0 -1 withscores)(连值带分数)
zrangebyscore key 开始score 结束score(ZRANGESCORE (60 (90)((是不包含的意思) limit
zrem key 某score下对应的value值,作用是删除元素
zcard/zcount key score区间/zrank key values值,作用是获得下标值/zscore key对应值,获得分数
zrevrank key values值,作用是逆序获得下标值。
zrevrange (逆序遍历)
zrevrangebyscore key
持久化
rdb(Redis DataBase)
在指定的时间间隔内将内存中的数据集快照写入磁盘。
也就是行话讲的Snapshot快照,它恢复时试讲快照文件读到内存中。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程不进行任何IO操作,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点就是最后一次持久化后的数据可能丢失。
RDB保存的是dump.rdb文件
save (意思是在多少秒内修改多少次)
默认:
是1分钟内改了1万次
或五分钟内改了10次
或15分钟内改了1次
如果想禁用RDB持久化策略,只要不设置任何save指令,或者给save传入一个空字符串参数也可以。save ""
aof(Append Only File)
以日志的形式记录每个写操作,将Redis执行过程的所有写指令记录下来(读操作不记录),只许追加文件但不可以修改文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复操作。
rdb和aof可以共存,优先加载AOF
修复:Redis-check-aof --fix进行修复
Appendfsync:
Always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
Everysec:出厂默认推荐,异步操作,每秒记录,如果一秒内宕机,有数据丢失
No
建议同时开启两种持久化方式
在这种情况下,redis重启的时候会优先加载AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的时候数据集要比RDB文件保存的数据集要完整,RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?作者建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而不会有AOF可能潜在的bug,留着作为一个万一的手段。
Redis的事务:
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞
一个队列中,一次性、顺序性、排他性的执行一系列命令。
MULTI:开启事务
EXEC:执行事务
DISCARD:取消事务
Redis是部分支持事务
watch监控
悲观锁/乐观锁/CAS(check and set):
悲观锁,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁,顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适合于多读的应用类型,这样可以提高吞吐量。
乐观锁策略:提交版本必须大于记录当前版本才能执行更新。
WATCH key
监控一个(或多个key)如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
UNWATCH
取消WATCH命令对所有key的监视。
一旦执行了exec之前加的监控锁都会被取消掉了。
watch指令,类似乐观锁,事务提交时,如果key值已被别的客户端改变,比如某个list已被别的客户端push/pop过了。整个事务队列都不会被执行。
通过watch命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。
特性:(部分支持事务)
单独的隔离操作
没有隔离级别的概念
不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令任然会被执行,没有回滚。
redis主从复制,读写分离
怎么玩:
1.配从(库)不配主(库)info replication
2.从库配置:slaveof主库IP 主库端口(SLAVEOF 127.0.0.1 6379)
每次与master断开后,都需要重新连接,除非你配置进redis.conf文件
3.修改配置文件细节操作
4.常用3招
1)一主二从(主机挂了,从机原地待命)
2)薪火相传(去中心化)
3)反客为主
SLAVEOF no one 使当前数据库停止与其他数据库的同步,转成主数据库
复制原理:第一次全量复制,第二次就是增量复制
哨兵模式(sentinel):(反客为主的自动版)
配置哨兵,填写内容;
sentinel monitor被监控数据库名字(自己起名字) 127.0.0.1 6379 1
上面最后一个数字1,表示主机挂掉后slave投票看让谁接替成为主机,得票数多少后成为主机
一组sentinel能同时监控多个Master
复制的缺点:复制延时
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很忙时,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。