Redis
1 redis是什么?
通常而言目前的数据库分类有几种,包括 SQL/NSQL,,关系数据库,键值数据库等等 等,分类的标准也不以,Redis本质上也是一种键值数据库的,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点。从而使它的位置处于关系数据库和键值数 据库之间。Redis不仅能保存Strings类型的数据,还能保存Lists类型(有序)和Sets类型(无序)的数据,而且还能完成排序(SORT) 等高级功能,在实现INCR,SETNX等功能的时候,保证了其操作的原子性,除此以外,还支持主从复制等功能。
2 Redis用来做什么?
通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求。而通常在一个电商类型的数据处理过程之中,有关商品,热销,推荐排序的队列,通常存放在Redis之中,期间也包扩Storm对于Redis列表的读取和更新。
3 Redis的优点
性能极高 – Redis能支持超过 100K+ 每秒的读写频率。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
4 Redis的缺点
是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
总结: Redis受限于特定的场景,专注于特定的领域之下,速度相当之快,目前还未找到能替代使用产品。
Redis是什么?两句话可以做下概括:
1. 是一个完全开源免费的key-value内存数据库
2. 通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets
Redis不是什么?同样从两个方面来做下对比:
1. 不是sql server、mySQL等关系型数据库,主要原因是:
. redis目前还只能作为小数据量存储(全部数据能够加载在内存中) ,海量数据存储方面并不是redis所擅长的领域
. 设计、实现方法很不一样.关系型数据库通过表来存储数据,通过SQL来查询数据。而Redis通上述五种数据结构来存储数据,通过命令 来查询数据
2. 不是Memcached等缓存系统,主要原因有以下几个:
.网络IO模型方面:Memcached是多线程,分为监听线程、worker线程,引入锁,带来了性能损耗。Redis使用单线程的IO复用模型,将速度优势发挥到最大,也提供了较简单的计算功能
.内存管理方面:Memcached使用预分配的内存池的方式,带来一定程度的空间浪费 并且在内存仍然有很大空间时,新的数据也可能会被剔除,而Redis使用现场申请内存的方式来存储数据,不会剔除任何非临时数据 Redis更适合作为存储而不是cache
.数据的一致性方面:Memcached提供了cas命令来保证.而Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断
. 存储方式方面:Memcached只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能
一句话小结一下:Redis是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。
Redis有什么用?只有了解了它有哪些特性,我们在用的时候才能扬长避短,为我们所用:
1. 速度快:使用标准C写,所有数据都在内存中完成,读写速度分别达到10万/20万
2. 持久化:对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上,主要有两种策略,一是根据时间,更新次数的快照(save 300 10 )二是基于语句追加方式(Append-only file,aof)
3. 自动操作:对不同数据类型的操作都是自动的,很安全
4. 快速的主--从复制,官方提供了一个数据,Slave在21秒即完成了对Amazon网站10G key set的复制。
5. Sharding技术: 很容易将数据分布到多个Redis实例中,数据库的扩展是个永恒的话题,在关系型数据库中,主要是以添加硬件、以分区为主要技术形式的纵向扩展解决了很多的应用场景,但随着web2.0、移动互联网、云计算等应用的兴起,这种扩展模式已经不太适合了,所以近年来,像采用主从配置、数据库复制形式的,Sharding这种技术把负载分布到多个特理节点上去的横向扩展方式用处越来越多。
这里对Redis数据库做下小结:
1. 提高了DB的可扩展性,只需要将新加的数据放到新加的服务器上就可以了
2. 提高了DB的可用性,只影响到需要访问的shard服务器上的数据的用户
3. 提高了DB的可维护性,对系统的升级和配置可以按shard一个个来搞,对服务产生的影响较小
4. 小的数据库存的查询压力小,查询更快,性能更好
写到这里,可能就会有人急不可待地想用它了,那怎么用呢?可以直接到官方文档,里面帮我们整理好了各个语言环境下的客户端,主要有Ruby、Python、 PHP、Perl、Lua、Java、C#....有几种语言,我也没见过,所以就不多说了,你懂的....
最后,把我使用过程中的一些 经验与教训,做个小结:
1. 要进行Master-slave配置,出现服务故障时可以支持切换。
2. 在master侧禁用数据持久化,只需在slave上配置数据持久化。
3. 物理内存+虚拟内存不足,这个时候dump一直死着,时间久了机器挂掉。这个情况就是灾难!
4. 当Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了,就开始做swap,内存碎片大
5. 当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间.
6. redis与DB同步写的问题,先写DB,后写redis,因为写内存基本上没有问题
---------------------
一、为什么使用
- 解决应用服务器的cpu和内存压力
- 减少io的读操作,减轻io的压力
- 关系型数据库的扩展性不强,难以改变表结构
二、优点:
- nosql数据库没有关联关系,数据结构简单,拓展表比较容易
- nosql读取速度快,对较大数据处理快
三、适用场景:
- 数据高并发的读写
- 海量数据的读写
- 对扩展性要求高的数据
四、不适场景:
- 需要事务支持(非关系型数据库)
- 基于sql结构化查询储存,关系复杂
五、Redis结构:
Redis是一个开源的key—value型数据库,支持string、list、set、zset和hash类型数据。对这些数据的操作都是原子性的,redus为了保证效率会定期持久化数据。
六、使用场景:
- 配合关系型数据库做高速缓存
- 缓存高频次访问的数据,降低数据库io
- 分布式架构,做session共享
- 可以持久化特定数据。
- 利用zset类型可以存储排行榜
- 利用list的自然时间排序存储最新n个数据
七、Linux下redis:
- redis目录:usr/local/bin
- linux下redis常用命令:
- redis-benchmark:性能测试工具
- redis-server:启动redis服务器
- redis-cli:启动redis客户端,操作入口
八、Redis基础知识
- 端口:6379
- 默认16个数据库,下标从0开始
- 单线程:redis是单线程+io多路复用:检查文件描述的就绪状态
Memchached:多线程+锁
- redis数据类型:String set list hash zset
九、Redis命令:
- key操作
keys * | 查看当前库所有的键 |
exists <key> | 判断是否存在key |
del <key> | 删除某个键 |
expire <key> <second> | 设置键过期时间 单位是s秒 |
ttl <key> | 查看还有多少秒过期 -1表示用不过期 -2表示已经过期 |
move <key> <db> | 把键移到另一个库下 |
dbsize | 查看数据库key的数量 |
flushdb | 清空当前库 |
flushall | 通杀所有库 |
- String类型:String是二进制安全的,可以包含任何数据源,最大512m
get <key> | 查看对应的键值 |
set <key> <value> | 添加键值对 |
append <key> <value> | 将给定的value 追加到原值的末尾 |
strlen < key > | 获取值得长度 |
setnx <key> <value> | 当key 不存在的时候设置key值 |
incr <key> | 将key中储存的数字加1,如果为空,则值为1 |
decr <key> | 将key中储存的数字减1,如果为空,则值为-1 |
incrby/decrby <key> <步长> | 将key中的数字增减 |
String批量处理:
mset <key1> <value1> <key2> <value2> | 同时设置多个键值对 |
mget <key1> <key 2> | 同时获得多个值 |
msetnx <key1> <value1> <key2> <value2> | 当给定的key都不存在 |
getrange <key> <start> <stop> | 类似sunstring |
setrange <key> <start> <stop> | 类似sunstring覆盖原始值 |
setex <key> <过期时间> <value> | 设置键值的同时,给定过期时间 |
getset <key> <value> | 以旧换新,设置了新的值同时得到旧值 |
- List:链表
1、特点:
单键多值
Redis列表是简单的字符串列表,从左或者从右插入
底层是双向链表,对两端的操作性能很高,通过下标查询性能很低
lpush/rpush <key> <value1> <value2> .. | 从左或从右插入多个值 |
lpop/rpop <key> | 从左边或右边吐出一个值,值光键亡 |
rpoplpush <key1> <key2> | 从key1 右边吐出一个值到key2的左边 |
lrange <key> <index> | 按照索引下标获取元素 从左到右 |
lindex <key> <index> | 按照索引下标获取元素 从左到右 |
llen <key> 获取列表长度 | 获取列表长度 |
linsert <key> before <value> <newvalue> | 在key中value前插入newvalue |
- Set:类似list的无序集合,保证列表中不会有重复数据,底层是一个value为null的hash表
sadd <key> <value1> <value2> | 将多个元素加入到key中,重复值忽略 |
smembers <key> | 取出该集合的所有值 |
sismember <key> <value> | 判断集合key中是否有该value值 有就1 没有0 |
scard <key> | 返回该集合的元素个数 |
srem <key> <value1> <value2> | 删除集合中的某个元素 |
spop <key> | 随机吐出该集合一个值 |
srandmember <key> <n> | 随机从集合中取出n个值,不会从集合中删除 |
smove <key1> <key2> <value> | 将key1中的value 移动到key2 中 |
sinter <key1> <key2> | 返回两个集合的交集元素 |
sunion <key1> <key2> | 返回两个集合的并集 |
- hash:键值对集合,类似map<String,Object>
hset <key> <filed> <value> | 给key 集合中的file 键赋值value |
hget <key1> <field> | 从key1 集合file取出value |
hmset <key1> <field1> <value1> <field2> <value2> | 批量设置hash的值 |
hexists <key> <field> | 查看key中的field 是否存在 |
hkeys <key> | 列出key中所有的filed |
hvals <key> | 列出该hash集合中所有的value |
- zset:与set集合非常相似,每个成员都关联了score,可以用来排序
zadd<key><score1><value1><score2><value2> | 将一个或多个元素以及score加入zset |
zrange<key><start><stop> withscore | 返回下标在区间内的集合,带有score |
zrangebyscore <ket> <min> <max>[withscore] [limit offset count] | 返回key中 score介于min和max中的成员,升序排列 |
zrevrangerbyscore <key> <min> <max> [withscore] [limit offset count] | 降序 |
zincrby <key> <increment> <value> | 在key集合中的value上增加increment |
zrem <key> <value> | 删除key集合下的指定元素 |
zcount <key> <min><max> | 统计 区间内的元素个数 |
zcord <key> | 获取集合中的元素个数 |
zrank <key><value> | 查询value在key中的排名,从0开始 |
十、redis持久化:
- 两种方式:rdb(redis database)和aof(append of file)
- RDB:在指定时间间隔内,将内存中的数据作为一个快照文件(snapshot)写入到磁盘,读取的时候也是直接读取snapshot文件到内存中
①持久化过程:redis单独创建(fork)一个进程来持久化,会先将数据写入临时文件中,待上次持久化结束后,会将该临时文件替换上次持久化文件,比aof高效,但是最后一次数据可能会丢失
②Fork:在linux中,fork()会产生一个跟主进程一样的子进程,出于效率考虑,主进程和子进程会公用一段物理内存,当发生改变的时候,才会把主进程“”写时复制”一份给子进程
③Redis备份的文件:在redis.conf中设置,dbfilename默认为:dump.rdb
④ Rdb保存策略:
- 900s 1 file change
- 300s 10file change
- 60s 10000file change
⑤Rdb的备份:
- config get dir 得到备份的文件夹
- 复制备份文件
⑥Rdb恢复:
- 关闭redis
- 将备份文件复制到工作目录下
- 启动redis,自动加载
- AOF : 以日志形式记录每个写操作,启动时通过日志恢复操作
- 开启AOF:默认不开启,进入redis.conf找到appendonly yes打开
- 修复AOF:redis-check-aof –fix appendonly.aof
- 同步频率:每秒记录一次,如果宕机该秒记可能失效
- Rewrite:bgrewriteaof 因为日志是追加方式,文件会越来越大,当超过了设置的阈值时,日志文件会压缩,保留仅可以恢复的日志
- RDB和AOF对比
- 节省磁盘空间
- 恢复速度快
- RDB优点:
- ROD缺点:
- 数据太大时,比较消耗性能
- 一段时间保存一次快照,宕机时最后一次可能没有保存
c) AOF优点:
i. 备份机制更加稳健
ii. 可读的日志文件,通过aof恢复更加稳健,可以处理失误
d) AOF缺点:
i. 比RDB更占磁盘
ii. 备份速度较慢
- iii每次都同步日志,有性能压力
- RDB和AOF哪个好
- 官方推荐都启用
- 对数据不敏感,单独用RDB
- 不建议单独使用AOF
- 若作为纯缓存使用,可以都不开启
十一、Redis事务:输入multi,输入的命令都会依次进入到队列中,但不会执行,直到输入exec,redis会将之前命令队列中的命令依次执行,通过discard可以放弃组队。
- 主要作用:序列化操作,串联多个命令防止别的命令插队
- 悲观锁:每次拿到数据的时候都会上锁,或者等待别人处理完再去拿锁,传统的关系型数据库里边很多用到了这种锁机制,比如行锁、表锁、读锁、写锁
- 乐观锁:每次拿数据的时候总认为别人不会修改数据,所以不会上锁。但是更新的时候回去判断别人有没有更改数据,使用版本号机制。乐观锁适用于多读的应用类型,可以提高吞吐量。
- Redis使用乐观锁:redis就是利用check-and-set机制实现事务
- 三大特性:
- 单独的隔离操作:事务中的所有命令都会序列化,按顺序执行。不会被其他客户端打断
- 没有隔离级别概念:队列中的命令没有提交之前不会被执行,事务外不能查看事务内的更新
- 不能保证原子性:跳过错误,依旧执行,没有回滚
十二、Redis订阅/发布:
是进程中的一种消息通信模式,发送者pub发送消息,订阅者sub接收消息 剩下的略。。。
十三、Redis主从复制:
- 是什么:主从复制就是主机数据更新后根据配置和策略,自动同步到备份机的master/slaver机制,master写为主,slave读为主
- 用处:
- 读写分离,性能拓展。
- 容灾快速恢复
- 配置服务器(配从不配主):
- 拷贝多个redis.conf文件
- 开启daemonize yes
- Pid文件名字
- 指定端口
- Log文件名字
- Dump.rdb名字
- Appendonly 关掉或者换名字
十四、Jedis:
- 所需jar包:
- common-pool-1.6jar包
- jedis-2.1
- 获取jedis对象:Jedis jedis = new Jedis(“ip” ,端口号);
十五、集群分布:
实现对redis的水平拓展,启动n’的redis节点,将整个数据分布在这n个节点中
- 配置conf文件:
- 拷贝多个redis.conf文件
- 开启daemonize yes
- Pid文件名字
- 指定端口
- Log文件名字
- Dump.rdb名字
- Appendonly 关掉或者换名字
- 配置cluster文件:
- cluster-enable yes 打开集群模式
- cluster-config-file xxx.conf 设置生成的节点配置文件名
- cluster-node-timeout 15000设置节点失联时间,超多该时间(毫秒),集群自动进入主从切换