Redis基础知识入门
- redis的介绍
- 概念:Remote Dictionary Server(Redis) 是一个开源的由Salvatore Sanfilippo使用ANSI C语言编写的key-value数据存储服务器。其值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型,所以它通常也被称为数据结构服务器。
- 与MySQL的对比:
- MySQL是关系型数据库,是持久化存储的,查询检索的话,会涉及到磁盘IO操作,为了提高性能,可以使用缓存技术,而memcached就是内存数据库,数据存储在内存中(当然也可以进行持久化存储),可以用作缓存数据库。用户首先去memcached查询数据,如果未查询到(即缓存未命中),才去MySQL中查询数据,查询到的数据会更新到缓存数据库中,提供给下次可能进行的查询。提高了数据查询方面的性能。
- Redis和memcached都是缓存数据库,可以大大提升高数据量的web访问速度。但是memcached只是提供了简单的数据结构string,而Redis的value可以是string、list、set、hash、sorted set这些,功能更加强大。
- web应用中一般采用MySQL+Redis的方式,web应用每次先访问Redis,如果没有找到数据,才去访问MySQL。
- Redis是内存数据库,数据保存在内存中,访问速度快。MySQL是关系型数据库,功能强大,存储在磁盘中,数据访问速度慢。像memcached,MongoDB,Redis等,都属于No sql系列。
- 应用场景:
1)用来做缓存-redis的所有数据是放在内存中的。
2)可以在某些特定应用场景下替代传统数据库--比如社交类的应用。
3)在一些大型系统中,巧妙的实现一些特定的功能:session共享、购物车、购物秒杀方案。
- redis的下载和安装
- gcc的安装:yum -y install gcc (gcc是linux下一个编译器集合)
- 解压:tar -zxvf redis-4.0.1tar.gz
- 切换目录:cd redis-4.0.1 执行命令:make(编译)
三、redis的基本操作
1、redis的启动:首先进入redis-4.0.1/src/ 目录下,./redis-server ../redis.conf,第一次是前台登录,一旦退出就是关闭redis,那该怎么实现后台登录?
关闭redis: ./redis-cli shutdown 就可以了,不建议kill,不温柔。
2、如果我想远程连接redis,需要注意些什么呢?
注意:
远程连接redis需要修改redis主目录下的redis.conf配置文件:
1)bind ip 绑定ip注释掉;
2)protected-mode yes 保护模式改为no;
3、redis客户端:redis命令行客户端、redis远程客户端、redis编程客户端
Redis命令行客户端:直接连接redis(./redis-cli 默认ip:127.0.0.1,端口号:6379)
Redis远程客户端:如redisDesktopManager
Redis编程客户端:分为Jedis和Lettuce。jedis是Java编程客户端,是一个很小很健全的redis的Java客户端;Lettuce是一个可伸缩线程安全的redis客户端,多个线程可以共享同一个redisConnection。
4、redis初相识
./redis-cli 进入redis命令行客户端
ping 返回PONG,表示redis服务运行正常
redis 默认为16个库,自动使用0号库。
select db 选择使用的库
flushall 删除所有库的数据
flushdb 删除当前库的数据
config get * 获得redis的所有配置值
exit 退出当前redis的连接
dbsize 当前库的key的数目
info 查看redis服务器的统计信息
5、redis的key命令
keys * 列出所有的key
exists key 检查某个key是否存在
move key db 将当前库的key移动到给定的库db中
expire key seconds 设置key的过期时间
ttl key 查看key还有多久过期 -1表示永不过期、-2表示不存在或者已经过期。
type key 查看key存储的值的类型
del key 删除key
四、redis的五种数据类型
1、字符串类型(String):字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON化的对象甚至是一张图片。
set key value 赋值操作
get key 取值操作
incr key 将 key 中储存的数字值加1,如果 key 不存在,则 key 的值先被初始化为 0 再执行 INCR 操作(只能对数字类型的数据操作)
decr key 同上,但是是减少。
setex key seconds value 设置key的值,并赋予有效时间
setnx key value 不存在值则赋值(1),存在则不赋值(0)
getset key value 获取旧值,赋予新值
2、hash是一个string类型的field和value的映射表,hash特别适合存储对象。
Hset 将哈希表hash中的域key的值设为value
Hget 获取哈希表hash中指定域key的值
Hmset 同时将多个key-value对设置到哈希表hash中
Hmget 获取哈希表hash中一个或者多个指定域key的值
Hgetall 获取哈希表key中所有的域和值
Hdel 删除哈希表 key 中的一个或多个指定域field
Hkeys 查看哈希表 key 中的所有field域
Hvals 查看哈希表 key 中所有域的值
3、list是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)
Lpush 将一个或多个值 value 插入到列表 key 的表头(最左边)
Rpush 将一个或多个值 value 插入到列表 key 的表尾(最右边)
Lrange 获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,1 表示列表的第二个元素, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
Lpop 从左边获取列表 key 的一个元素,并将该元素移除
Rpop 从右边获取列表 key 的一个元素,并将该元素移除
Lindex 获取列表 key 中下标为指定 index 的元素
Llen 获取列表 key 的长度
4、set是string类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数据。
Sadd 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的member 元素将不会再加入
Smembers 获取集合 key 中的所有成员元素
Sismember 判断 member 元素是否是集合 key 的成员
Scard 获取集合里面的元素个数
Srem 删除集合 key 中的一个或多个 member 元素
5、Redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员。不同的是zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。
Zadd 将一个或多个 member 元素及其 score 值加入到有序集合 key 中
Zrem 删除有序集合 key 中的一个或多个成员
Zcard 获取有序集 key 的元素成员的个数
Zrank 获取有序集 key 中成员 member 的排名,有序集成员按 score 值从小到大顺序排列
Zrevrank 获取有序集 key 中成员 member 的排名,有序集成员按 score 值从大到小顺序排列
Zrange 获取有序集 key 中,指定区间内的成员,按 score 值从小到大排列
五、redis的发布与订阅
- 认识消息队列
消息队列的三要素:生产者producer、消费者consumer、消息服务broker
消息队列的类型:点对点(point to point)、发布与订阅(pub/sub)
消息队列用途:实现系统解耦、削峰填谷、顶住流量洪峰
2、什么是发布订阅?
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(publish)发送消息 ,订阅者(subscribe)接收消息。
发布订阅也叫生产者消费者模式,是实现消息队列的一种方式
3、如何实现发布与订阅?
开启3个redis客户端,2个订阅服务,一个发布服务
让消息订阅者订阅某个频道主题:subscribe channel
让消息发布者向频道主题上发布消息:publish channel message
然后观察消息的发布与订阅情况
六、redis的事务
1、事务的概念
事务指的是一系列的操作步骤,这一系列操作步骤,要么完全成功,要么完全的不执行。
比如微博中:A用户关注了B用户,那么A关注列表中就会有B用户,B的粉丝列表中有A用户。
Redis中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令,redis事务保证这些命令被执行时中间不会被任何其他操作打断。
2、redis对事务的控制
Muliti 用MULTI命令告诉Redis,接下来要执行的命令你先不要执行,而是把它们暂时存起来 (开启事务)
Exec 告知redis执行前面发送的命令(提交事务)
Discard 放弃事务
正常情况:
异常情况:
例外情况:
k1赋值了,但是incr k1 命令是错误的。
放弃情况:
乐观锁在redis事务中的应用
悲观锁:悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改该数据,所以每次在拿数据的时候都会先上锁,这样别人想拿这个数据就会block阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,让别人无法操作该数据。
乐观锁:
乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改该数据,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这条数据,一般使用版本号机制进行判断。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
乐观锁大多数情况是基于数据版本号(version)的机制实现的。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表添加一个“version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据,不予更新。
用watch机制实现redis的乐观锁
七、redis的持久化
1、持久化的概念:持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而放在磁盘就算是一种持久化。
Redis的数据存储在内存中,内存是瞬时的,如果linux宕机或重启,又或者Redis崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
2、RDB方式
RDB概念:Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB的实现;只需要在redis.conf文件中进行配置即可,配置文件redis.conf中搜索 SNAPSHOTTING
优点:由于存储的是数据快照文件,恢复数据很方便,也比较快
缺点:会丢失最后一次快照以后更改的数据
如果你的应用能容忍一定数据的丢失,那么使用rdb是不错的选择
如果你不能容忍一定数据的丢失,使用rdb就不是一个很好的选择
由于需要经常操作磁盘,RDB 会经常 fork 出一个子进程。如果你的redis数据库很大的话,Fork 占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别),如果你的数据库超级大并且你的服务器CPU比较弱,有可能是会达到一秒。
3、AOF方式
AOF的概念:Append-only File(AOF),Redis每次接收到一条改变数据的命令时,它将把该命令写到一个AOF文件中(只记录写操作,读操作不记录),当Redis重启时,它通过执行AOF文件中所有的命令来恢复数据。
AOF的实现:AOF方式的数据持久化,仅需在redis.conf文件中配置即可。在redis.conf配置文件中搜索APPEND ONLY MODE
总结:append-only 文件是另一个可以提供完全数据保障的方案;
AOF 文件会在操作过程中变得越来越大。比如,如果你做一百次加法计算,最后你只会在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录对最终的结果是无用的;
但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小;
可以同时使用这两种方式,redis默认优先加载aof文件;
八、redis的集群
1、redis主从复制(master/slave)
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
那么这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,那该怎么实现呢?
Redis提供了复制(replication)功能来自动实现多台redis服务器的数据同步。
我们可以通过部署多台redis,并在配置文件中指定这几台redis之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即master/slave,并且redis默认master用于写,slave用于读,向slave写数据会导致错误。
修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从而构成主从复制的关系。
打开三个界面,分别进入不同端口号的命令行客户端。
info replication 查看redis服务器所处角色
主服务上可以进行读写操作
从服务器只能进行读操作
2、Redis容灾处理
当Master服务出现故障,需手动将slave中的一个提升为master, 剩下的slave挂至新的master上(冷处理)
随机将一台从服务器提升为主服务器,此时没有从服务器。
将其他从服务器挂到新的主服务器下
此时查看主服务器的配置信息
总结:一个master可以有多个slave
slave下线,读请求的处理性能下降
master下线,写请求无法执行
当master发生故障,需手动将其中一台slave使用slaveof no one命令提升为master,其它slave执行slaveof命令指向这个新的master,从新的master处同步数据
主从复制模式的故障转移需要手动操作,要实现自动化处理,这就需要Sentinel哨兵,实现故障自动转移
3、高可用sentinel哨兵
1)监控
Sentinel哨兵是redis官方提供的高可用方案,可以用它来监控多个Redis服务实例的运行情况。
Sentinel会不断检查Master和Slave是否正常
如果Sentinel挂了,就无法监控,所以需要多个哨兵,组成Sentinel网络
监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监控服务器的信息
当一个Sentinel认为被监控的服务器已经下线时,它会向网络中的其它Sentinel进行确认,判断该服务器是否真的已经下线
如果下线的服务器为主服务器,那么Sentinel网络将对下线主服务器进行自动故障转移,通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转移到新的主服务器下,以此来让系统重新回到正常状态
下线的旧主服务器重新上线,Sentinel会让它成为从,挂到新的主服务器下
- Sentinel配置
复制三份sentinel.conf文件
三份sentinel配置文件修改:
1、修改 port 26380、 port 26381、 port 26382
2、修改 sentinel monitor mymaster 127.0.0.1 6380 2
Sentinel会根据Master的配置自动发现Master的Slave
Sentinel默认端口号为26379
执行以下三条命令,将创建三个监视主服务器的Sentinel实例:
./redis-sentinel ../sentinel26380.conf
./redis-sentinel ../sentinel26381.conf
./redis-sentinel ../sentinel26382.conf
主服务器是6381
关闭6381主服务器
投票决定新的主服务器
6380变为新的主服务器
重启启动6381,变为从服务器
总结:主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降,Master下线,写请求无法执行
Sentinel会在Master下线后自动执行故障转移操作,提升一台Slave为Master,并让其它Slave成为新Master的Slave
Redis总结:
redis足够简单和稳定
支持丰富的数据结构
内存存储读写性能优秀
提供持久化的支持
支持部分事务操作