nosql数据库四大分类
- kv键值对:redis、menmcache、tair(淘宝自研分布式存储引擎)
- 文档型数据库(bson格式,类似于json):mangodb、conchdb
- 列存储数据库:Hbase、分布式文件存储系统
- 图关系数据库(不是存放图,而是存放的关系,例如社交网络):neo4j、infoGrid
redis的安装
linux下:
- 解压redis安装包
- yum install gcc -c++(gcc是编译器套件,该命令是下载安装c++编译器)
- make(编译)
- make install(安装)
- 拷贝redis.conf ,编辑配置文件(其中,由于redis默认不是后台启动的,所以需要把配置文件中daemonize:no 改为daemonize:yes)
- redis-server 目录/redis.conf (启动redis服务)
- redis-cli -h 127.0.0.1 -p 6379 >>ping(客户端直接访问服务,默认IP和端口号,可修改)
redis 性能测试
redis自带的性能测试工具;redis-banchmark
命令:redis-benchmark - h 127.0.0.1 -p 6379 -c 100(100并发数)-n 10000(10000次请求)
redis默认16个数据库
配置文件中有
databases 16
默认使用的是第0个数据库,相关操作命令:
select 3 切换第四个数据库
- config get databases 查询数据库个数
- dbsize 查看当前数据库key的数量
- flush清除当前数据库数据
- flushall清楚所有数据库中所有数据 # redis是单线程的 redis是内存数据库,cpu不是redis的性能瓶颈,redis的性能瓶颈是网络宽带和内存。所以选择了单线程,而且多线程上下文切换的耗费时间和资源。
key的操作命令
- keys * 显示所有key
- get ‘name’ 获取指定key的值
- set key1 value1 设置添加key的值
- exists keyname判断指定key是否存在
- move keyname 1移动到数据库1
- del keyname 删除key
- expire keyname 10 设置key的过期时间,单位:秒
- ttl keyname查看指定key的剩余过期时间,为负数时,表示已过期
- type keyname查看key的value的数据类型
value的五大基本数据类型
五大数据类型:string、list、set、hash、zset
1、String类型
- append keyname “hello” 指定key的value后追加字符串,如果指定key不存在,相当于set key1 value1;
- strlen keyname 获取value字符串的长度;
- incr keyname 使value数值自增1;
- decr keyname 使value数值自减1;
- incrby keyname 10使value数值增加指定的数(博客浏览量动态计数使用);
- decrby keyname 10使value的值减少指定的数;
- setex(set with expire)keyname 30 设置过期时间;
- setnx(set if not exist ) key1 value1 不存在设置(分布式锁中会常用),不存在创建成功,存在创建失败;
- mset k1 v1 k2 v2 批量set;
- mget k1 k2批量get;
- msetnx k1 v1 k3 v3原子性批量set,要么key都不存在,都可以设置成功,要么只要有一个key已存在,就都不可以设置成功;
- getset k1 v1先反回k1的值,没有则反回null,然后再给key1设置一个姓的值;
- set user:1 {name:zhangsan,arg:23}设置一个user:1对象,值为json串表示对象;
- mset user:1:name zhangsan user:1:age 23 批量设置对象属性值;
- mget user:1:name user:1:age批量获取对象属性值;
2、list
redis中list是链表,有序,可添加重复元素,可以用list实现栈、队列、阻塞队列
- lpush list1 var1从左端头部添加list元素;
- lrange list1 0 2 获取list的第1个到第3个元素(lrange list1 0 -1是获取全部元素);
- rpush list1 var1从右端尾部添加元素
- lpop list1 var1 移除左端头部第一个元素
- rpop list1 var移除又短尾部第一个元素
- lindex list1 0 通过下标获取对应元素
- llen获取list的长度
- lrem list1 1 var1 移除匹配指定元素值的1个元素
- ltrim list1 1 3剪除第二到第四元素之外的其他元素
- rpoplpush list1 list2 移除list1中最后一个元素,并将这个元素添加到list2中去;
- lset list1 0 var1将list中指定下标的元素替换,这个key或者对应下标元素不存在时,会失败
- linsert list1 after/before pivot var1 在元素pivot前或者后插入元素var1;
3、set
无序、不能添加重复元素
- sadd set1 var1添加元素
- smembers set1查看set1的所有元素
- sismember set1 var1 判断指定元素是否在集合中
- scard set1 获取集合中元素的个数
- srem set1 var1移除指定元素
- srandmember set1 n随机抽取出n个元素(srandmember set1随机抽取出一个元素);
- sdiff set1 set2 求差集(set1有,set2中没有的元素)
- sinter set1 set2 交集
- sunion set1 set2 并集
4、hash
理解: 存的是map ,key-map 》key-(field,val),更适合对象的存储
如hset user:1: name zhangsan, set user:1 age 23
- hset hash1 field1 val1添加元素
- hget hash1 field1获取元素
- hmset hash1 field1 var1 filed2 var2添加多个元素
- hmget hash1 field1 field2获取多个元素
- hlen hash1获取元素个数
- hdel hash1 field1删除指定元素
- hgetall hash1获取所有元素
- hexists hash1 field1判断指定元素是否存在
- hkeys hash1 获取所有field
- hvals hash1 获取所有val
- hincrby hash1 field1 2
- hdecrby hash1 field1 2
- hsetnx
5、zset
有序的set,在set的基础上加了排序
应用场景;排行榜,加权信息
- zadd zset1 1 val1添加一个元素
- zadd zset1 2 val2 3 val3添加多个元素
- zrange zset 0 -1
- rangebyscore zset1 -inf +inf升序排序(-inf与+inf代表正负无穷)
- rangebyscore zset1 -inf 3 withscores 序号小于等于3的排序,并显示序号值
- zrevrange zset1 -inf +inf降序排序
- zrem zset1 val1移除元素
- zcard zset1获取元素个数
- zcount zset1 1 3序号在1到3之间的元素个数
三大特殊数据类型
三大特殊数据类型:bitmaps, hyperloglogs 和 地理空间(geospatial)
1、geospatial
geospatial底层是zset
应用:定位、附近的人、打车距离
将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
当坐标位置超出上述指定范围时,该命令将会返回一个错误。
它是如何工作的?
sorted set使用一种称为Geohash的技术进行填充。经度和纬度的位是交错的,以形成一个独特的52位整数. 我们知道,一个sorted set 的double score可以代表一个52位的整数,而不会失去精度。
这种格式允许半径查询检查的1 + 8个领域需要覆盖整个半径,并丢弃元素以外的半径。通过计算该区域的范围,通过计算所涵盖的范围,从不太重要的部分的排序集的得分,并计算得分范围为每个区域的sorted set中的查询。
使用什么样的地球模型(Earth model)?
这只是假设地球是一个球体,因为使用的距离公式是Haversine公式。这个公式仅适用于地球,而不是一个完美的球体。当在社交网站和其他大多数需要查询半径的应用中使用时,这些偏差都不算问题。但是,在最坏的情况下的偏差可能是0.5%,所以一些地理位置很关键的应用还是需要谨慎考虑。
- geoadd China:city 116.40 39.90 beijing添加地理位置元素
- geopos china:city beijing获取经纬度
- geodist china:city Beijing wuhan km 两个城市之间的距离(m米,km千米、mi英里、ft英尺)
- georedius china:city 110 30 1000km (加withdist可以显示每个元素与中心点间的直线距离;加withcoord可以显示每个元素经纬度;加count n限制查出元素为n个。)以经纬度110,30的位置为中心查找1000km以内的位置元素
- georadiusbymember china:city Beijing 1000km 以地理位置元素为中心查询1000km范围内的其他元素
- gethash china:city beijing 获取元素经纬度的geohash值
2、 hyperloglogs
应用场景:允许一定错误率的计数,比如统计网站访问用户数
优缺点:优点:大数据量占用内存小,2^64元素的基数仅占用12kb;缺点:有0.81%的错误率
- pfadd hy1 a b c d d 创建一组元素
- pfcount hy1 获取元素基数(0.81%的错误率)
- pfmerge hy hy1 hy2 合并hy1与hy2得到并集hy
3、bitmaps
位存储,操作二进制
应用场景:统计用户活跃、不活跃;登陆、未登录;打卡统计;
- setbit bm1 1 0添加元素
例如存储一周打卡信息:
setbit bm1 1 0;
setbit bm1 2 0
setbit bm1 3 0
setbit bm1 4 0
setbit bm1 5 0
setbit bm1 6 0
setbit bm1 7 0 - getbit bm1 1 或周一是否打卡
- bitcount bm1 统计状态位1的元素个数
redis事物
redis事物本质是一组命令按顺序执行
- 开启事物(multi)
- 命令入队(……)
- 执行食物(exec)
discard取消事物
事物中存在命令编译错误(例如命令写错了),则整个事物无法执行;如果事务中存在运行时异常(例如incr一个非数值型数据),则异常命令执行失败,其他命令执行成功,所以redis事物是不保证原子性的。
乐观锁
set money 100
wacth money加监视器,获取money的值,监控值的变化,实现乐观锁效果
nowatch money去除监视器
jedis
jedis是redis官方推荐的java开发连接工具
- 导入对应的jedis依赖
- 使用
springboot整合redis
springboot操作数据库数据spring-data(包含jpa、jdbc、redis、mangodb)
springboot2.x之后,原来的jedis被替换成了lettuce
jedis:jedis是直连,多线程下不安全,避免线程不安全,就得使用jedispool,类似bio
lettuce:底层使用了netty,可多线程共享,且线程安全,类似nio;
springboot整合redis
自定义redisTemplate
redis配置文件详解
持久化rdb与aof
持久化;生成一个数据文件保存到硬盘中
RDB
redis默认的持久化方式,文件:dump.rdb(配置在redis.conf中)
- 持久化触发条件:
1、配置文件中save规则满足的情况下
2、执行flushAll命令
3、正常退出redis - 恢复rdb数据
只要将rdb文件放到redis启动目录(命令config get dir获取启动目录)中,redis启动时会自动检查加载里面的数据。 - Rdb持久化优点
1、 持久化文件将只包含一个文件
2、 对灾难恢复,主从复制 效率比较高。
3、 持久化工作:子进程 - Rdb缺点
数据安全性不是很好 - Rdb数据持久化同步策略
缺省情况下,Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开redis.conf文件之后,我们搜索save,可以看到下面的配置信息:- save 900 1 #在900秒(15分钟)之内,如果至少有1个key发生变化(增删改),则dump内存快照。
- save 300 10 #在300秒(5分钟)之内,如果至少有10个key发生变化,则dump内存快照。
- save 60 10000 #在60秒(1分钟)之内,如果至少有10000个key发生变化,则dump内存快照。
AOF
以日志记录路写命令到aof文件。
默认配置
重写规则
aof重写配置
redis默认时不开启AOF持久化的,需手动私改配置
appendonly no 改no为yes
重启redis后生效
-
如果aof文件被破坏过,redis重启会失败,这时候可以用redis-check-aof修复文件aof;
-
aof优缺点
-
2.1、AOF的优点
(1)AOF可以更好的保护数据不丢失。
一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据,Redis进程挂了,最多丢掉1秒钟的数据;
(2)AOF日志文件以append-only模式写入,写入性能比较高
AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修;
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
因为在rewrite log的时候,会对其中的指令进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。
当新的merge后的日志文件ready的时候,再交换新老日志文件即可。
(4)适合做灾难性的误删除紧急恢复
AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据;
2.2、AOF的缺点
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大,恢复速度慢;
我们可以简单的认为AOF就是日志文件,此文件只会记录“变更操作”(例如:set/del等),如果server中持续的大量变更操作,将会导致AOF文件非常的庞大,意味着server失效后,数据恢复的过程将会很长;
事实上,一条数据经过多次变更,将会产生多条AOF记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为AOF持久化模式还伴生了“AOF rewrite”。
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的;
如果你要保证一条数据都不丢,也是可以的,AOF的fsync设置成没写入一条数据,fsync一次,那就完蛋了,Redis的QPS大降;
(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来
所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。
三、RDB和AOF到底该如何选择
1、不要仅仅使用RDB,因为那样会导致你丢失很多数据;
2、也不要仅仅使用AOF,因为那样有两个问题:
你通过AOF做冷备,没有RDB做冷备,恢复速度更快;
第二,RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug;
3、综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择;
用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复
- 使用方案扩展:
…… - 异地多活
redis发布订阅
- subscribe demo 订阅端订阅一个频道
- publish demo “hello” 发送端发送消息
命令:
-
Redis 配置文件位置查询
在redis内部执行命令: CONFIG GET *
一般情况下配置文件叫:redis.conf
-
ps -ef | grep redis-server 可以查看 redis进程,以及可以查看到安装路径等信息
-
redis key值获取
keys * 获取当前数据下所有KEY值
get key
set key value 设置key和值
select 2 切换到第二个数据库
-
info命令
转自:http://www.runoob.com/redis/server-info.html
info server : 一般 Redis 服务器信息,包含以下域:
info clients 表示已连接客户端信息 包含以下内容:
connected_clients 已连接客户端的数量(不包括通过从属服务器连接的客户端)
client_longest_output_list 当前连接的客户端当中,最长的输出列表
client_longest_input_buf 当前连接的客户端当中,最大输入缓存
blocked_clients 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
info cpu CPU 计算量统计信息
info mem 内存信息,包含以下:
- used_memory : 由 Redis 分配器分配的内存总量,以字节(byte)为单位;
- used_memory_human : 以人类可读的格式返回 Redis 分配的内存总量;
- used_memory_rss : 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致;
- used_memory_peak : Redis 的内存消耗峰值(以字节为单位);
- used_memory_peak_human : 以人类可读的格式返回 Redis 的内存消耗峰值;
- used_memory_lua : Lua 引擎所使用的内存大小(以字节为单位);
- mem_fragmentation_ratio : used_memory_rss 和 used_memory 之间的比率;
- mem_allocator : 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc ;
在理想情况下, used_memory_rss 的值应该只比 used_memory 稍微高一点儿;当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。内存碎片的比率可以通过 mem_fragmentation_ratio 的值看出。当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟。当 Redis 释放内存时,分配器可能会,也可能不会,将内存返还给操作系统。
如果 Redis 释放了内存,却没有将内存返还给操作系统,那么 used_memory 的值可能和操作系统显示的 Redis 内存占用并不一致。
查看 used_memory_peak 的值可以验证这种情况是否发生
info persistence RDB 和 AOF 的相关信息
info stats : 一般统计信息
info replication : 主/从复制信息
info commandstats Redis 命令统计信息
info cluster Redis 集群信息
info keyspace redis 数据库相关的统计
info keyspace redis 数据库相关的统计信息
-
slow log get 10 慢查询语句, 在上一个节中有讲过
http://www.cnblogs.com/huamei2008/p/8850047.html
-
Redis自身性能压测:
命令:
redis-benchmark -p 6379 -c 20000 -n 50000
-h 表示IP
-p 表示端口
-c 表示连接数
-n表示请求数
-t 后面跟请求方式, 如get
7、slaveof
slaveof no one 主从复制模式下主节点宕机后,设置从节点为主节点
redis集群
主从复制(一般最低一主二从):
1、主节点写,从节点只能读不能写;
2、主节点的数据会被自动被从节点保存;
主从复制原理
1、slave启动连接到master(未连接成功时,会重复发送请求)
2、slave连接master成功后会发送一个sync同步命令
3、master接收到命令后,启动后台存盘进程,收集所有修改数据集的命令,把数据文件发送给slave,完成一次同步;
- 完全复制:slave在接受到数据文件后,把数据文件存盘并加载到内存中;
- 增量复制:master每次数据修改时,会将修改数据的命令发送给slave,salve接受并执行;
slave每次重新连接上master时,都会发生一次完全复制。
主从复制优缺点:
优点:
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
- 为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成
- Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。
- Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
- Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据
缺点:
- Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
- 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
- Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
哨兵模式
解决问题:主从复制模式下,主节点宕机后,需要手动修改配置文件或者云命令,影响服务可用性和性能的问题;
原理:哨兵作为一个独立进程,通过向redis服务器发送命令,等待redis服务器响应,从而监控多个redis服务器,如图:
实际应用中,为了防止哨兵进程也出现异常停止的情况,通常会启动多个哨兵进程相互监听,如图:
当主节点宕机时,有一个哨兵发现主节点服务器不可用,这个时候不会发生failover(故障转移),这个现象就是主观下线;只有当发现主节点服务不可用的哨兵超过一定数量时,哨兵间会进行投票在从节点中选出主节点,然后根据投票结果,又一个哨兵进程发起,进行failover操作,修改选出的从节点的配置文件,使之成为主节点,主节点替换成功后,会通过发布订阅的模式,让各个哨兵把监控的这个从节点替换为主节点,这就客观下线。
使用:配置文件
sentinel monitor redisname(随意自定义) host port 2(2表示,两个哨兵发现主节点不可用时,执行failover),主节点切换后,原主节点恢复后自动变为从节点。
投票算法。。。。。
缓存穿透、缓存击穿、缓存雪崩及解决方案
1、缓存击穿:某条数据数据在redis缓存中找不到,数据库中也查不到,循环发送请求;
解决方案: