专栏首页前端迷超详细的redis入门

超详细的redis入门

目录:

  • redis简介
  • Linux环境安装redis
  • redis的数据类型和常用命令
  • redis多数据库
  • redis数据的持久化
  • redis的事务
  • Redis主从复制(读写分离)、主从切换(一主二从三哨兵)
  • redis发布订阅
  • redis单线程模型
  • redis批量执行命令
  • redis禁用或重命名危险命令

一、Redis简介

官网:https://redis.io/

1、什么是Redis?

Redis是一个完全开源免费的、遵守BSD协议的、高性能的key-value存储系统。它既可基于内存作为高性能缓存,也可将数据持久化到磁盘,是目前最热门的NoSql数据库之一。

了解:BSD协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。

2、我们为什么要使用Redis?

(1).缓存数据,减少对数据库的访问次数,提高响应速度;

(2).性能极高,Redis读取速度可达110000次/s,写速度可达81000次/s ;

(3).支持数据的持久化;

(3).支持丰富的数据结构:String(字符串)、Hash(散列)、List(列表)、Set(集合)以及zset(Sorted Set:有序集合);

......

3、Redis与Memcache的比较

Memcache

Redis

持久性

不支持持久化

支持将数据持久化到磁盘

灾难恢复

宕机后数据消失不可恢复

数据可恢复

支持的数据结构

简单的k/v类型

Hash、List、Set、zset等

虚拟内存

memcache所有数据全部一直存储在内存中,存储的数据量不能超过内存的大小。

虚拟内存:Redis会将暂时不常用的Values从内存交换到磁盘中,在内存中只保留Keys的数据,当这些被换出的Values需要被读取时,Redis则将其再次读回到主内存中。

并发

Memcache支持多线程,通过CAS实现线程安全保证数据的一致性;

Redis是单线程的,且Redis支持事务;

......

总结:Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcached只是简单的K/V缓存。有持久化需求或者对数据结构的处理有高级要求的应用,选择redis。简单的key/value存储,可以选择memcache。

4、Redis的使用场景

> 缓存热数据

> 计数器

> Redis 作分布式锁

> 最新列表

例如要展示最新新闻列表,如果总数量很大的情况下,尽量不要使用select a from A limit 10这种low操作,尝试redis的 LPUSH命令构建List。

> 排行榜

可以使用sorted set(有序集)来构建,命令:ZADD。

二、Linux安装Redis

(1)、安装gcc

gcc:linux系统编译器,如果没有安装,在执行make命令时会报Command not found;

>执行如下命令用来查看是否已安装gcc

# gcc -v

出现如下信息表示已安装:gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)

>否则,执行如下命令,先安装gcc

# yum install gcc-c++

(2)、安装tcl(非必须,如果不需要测试Redis也可以不安装)

tcl:tcl是一种脚本语言,而Redis的测试用例是tcl脚本,安装后如果需要测试Redis,我们就需要安装tcl解释器,否则在步骤(4)执行make test时会报:You need 'tclsh8.5' in order to run the Redis test。

执行如下命令安装tcl:

# cd /usr/local

# mkdir tcl

# cd tcl

# wget http://downloads.sourceforge.net/tcl/tcl8.6.3-src.tar.gz

# tar -zxvf tcl8.6.3-src.tar.gz

# cd tcl8.6.3/unix/

# ./configure

# make

# make install

(3)、安装Redis

# cd /usr/local

# mkdir redis

# cd redis

# wget http://download.redis.io/releases/redis-4.0.10.tar.gz

# tar -zxvf redis-4.0.10.tar.gz

# cd redis-4.0.10

# make

# make PREFIX=/usr/local/redis install

其中PREFIX=/usr/local/redis可以省略,省略redis默认会安装到/usr/local/bin目录下。

(4)、测试Redis

# cd src

# make test

通过以上命令就可以对redis进行测试。返回"\o/ All tests passed without errors!"表示所有测试都没有错误。

(5)、初步配置redis

# cd /usr/local/redis/redis-4.0.10

# vi redis.conf

修改redis配置文件中的如下两项:

> daemonize no ——> daemonize yes

配置redis作为守护进程运行。daemonize 设置为no时,退出或关闭终端都会导致redis进程退出;而设置为yes redis会在后台一直运行。

另外还有一个属性:

pidfile /var/run/redis_6379.pid,表示当redis服务以守护进程方式运行时,redis默认会把pid(进程Id)写入/var/run/redis_6379.pid,服务运行时该文件就存在,服务一旦停止该文件就自动删除。

> timeout 0 ——> timeout 600

表示客户端闲置多长时间关闭连接;

redis的配置参数很多,此处只修改两项最基本的配置,其他后面会涉及到的配置我们在后面会讲,剩余配置大家可自行了解。

(6)、设置redis开机自启动

# vi /etc/init.d/redis

init.d目录下原本不存在redis文件,执行vi /etc/init.d/redis时会新建redis文件;

> 找到redis启动脚本

# find / -name 'redis_init_script '

启动脚本所在路径:/usr/local/redis/redis-4.0.10/utils/redis_init_script

> 拷贝启动脚本文件

#cp /usr/local/redis/redis-4.0.10/utils/redis_init_script /etc/init.d/redis

> 修改redis文件

# vi /etc/init.d/redis

> 修改以下4处为自己的安装路径,保存

EXEC=/usr/local/redis/redis-4.0.10/src/redis-server

CLIEXEC=/usr/local/redis/redis-4.0.10/src/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid

CONF="/usr/local/redis/redis-4.0.10/redis.conf"

> 设置权限

# chmod 777 /etc/init.d/redis

> 设置开机自启动【此处的redis就代表之前init.d下的redis】

# chkconfig redis on

(7)、启动或关闭redis服务

# service redis start

# service redis stop

(8)、使用redis,简单示例如下【退出redis客户端命令:quit】

[root@JD /]# ./usr/local/redis/redis-4.0.10/src/redis-cli

127.0.0.1:6379> set felixRedis:username yuanlong

OK

127.0.0.1:6379> set felixRedis:password 111111

OK

127.0.0.1:6379> get felixRedis:username

"yuanlong"

127.0.0.1:6379> get felixRedis:password

"111111"

127.0.0.1:6379> quit

[root@JD /]#

三、Redis数据类型和常用命令

> Redis目前支持5种数据类型,分别是:

String(字符串)

Hash(散列)

List(列表)

Set(集合)

Sorted Set(zSet:有序集合)

下面分别介绍五种数据类型及相应的操作命令,Redis总共有14个命令组200多个命令。另外注意Redis的命令不区分大小写,但是key严格区分大小写。

>>> String(字符串):Value最大值为512M

命令

描述

set key value

设值,若给定的Key已经存在,则被覆盖

setnx key value

若给定的key不存在,执行set操作,返回1;若给定的Key已经存在,不做任何操作,返回0;

get key

获值

mset key value[key value ...]

同时设置一个或多个Key-Value键值对,如果某个给定key已经存在,那么MSET新值会覆盖旧值,mset是原子操作,所有Key都会在同一时间被设置

msetnx key value[key value ...]

同mset,但是仅当所有key都不存在时才会进行set操作

mget key [key ...]

返回一个或多个指定key对应的value,某个key不存在那么这个key返回nil

setex key seconds value

设置失效时间,单位s,原子操作,如:setex city 10 shanghai>设置失效时间还可以这样: set key value expire key 10【单位s】 pexpire key 10【单位ms】>查看缓存的失效时间:ttl key 当key不存在时,返回-2; 当key存在但未设置存活时间时,返回-1; 否则,返回key的剩余存活时间(单位s);

incr key

+1,若key不存在,先将key的值初始化为0再执行incr;特殊的String操作:INCR/DECR使用场景:统计在线人数、秒杀场景的库存增减;

decr key

-1,若key不存在,先将key的值初始化为0再执行decr

incrby key increment

+指定增量

decrby key decrement

-指定减量

>>> Hash(散列)

命令

描述

hset key field value

将哈希表key中的域field的值设为value;若key不存在,一个新的Hash表被创建;若field已经存在,旧的值被覆盖;

hget key field

获取哈希表key中给定域field的值

hdel key filed [field ...]

删除哈希表key中的一个或多个指定域,不存在的域将被忽略

hexists key field

查看哈希表key中,指定域field是否存在,存在返回1,不存在返回0;

hincryby key filed increment

为哈希表key中的域field加上增量increment,其余同INCR命令

hmset key field value [field value ...]

同时将多个field-value对设置到哈希表key中

hmget key field [field ...]

返回哈希表key中,一个或多个给定域的值,如果给定的域不存在于哈希表,返回nil;

hlen key

返回哈希表key中域的数量

hkeys key

返回哈希表key中的所有域

hvals key

返回哈希表key中所有的值

hgetall key

返回哈希表key中,所有的域值对

>>> List

命令

描述

lpush key value [value ...]

从左边插入一个元素(插入表头元素),key不存在时会创建一个新列表

lpushx key value

从左边插入一个元素(插入表头元素),key不存在时什么操作也不做

rpush key value [value ...]

rpushx key value

lpop key

移除表头元素并返回移除的元素

rpop key

移除表尾元素并返回移除的元素

lrange key start stop

返回列表key中指定区间内的元素,下标从0开始,闭区间;(1).start>stop或start>列表的最大下标,返回空列表;(2).stop>列表最大下标,按照stop=列表最大下标来返回;(3).可使用负数下标,-1表示列表最后一个元素,-2表示列表倒数第二个元素;

lrem key count value

移除count个列表中值为value的元素;(1).count>0表示从头到尾搜索,移除与value相等的元素,数量为count;(2).count<0表示从尾到头搜索,移除与value相等的元素,数量为count;(3).count=0表示移除表中所有与value相等的元素;

lindex key index

返回列表key中,下标为index的元素

lset key index value

将列表key中下标为index的元素值设为value

linsert key BEFORE|AFTER pivot value

(1).将值value插入列表key中,位于pivo之前或之后;(2).当pivot不存在于列表key时,不执行任何操作;(3).当key不存在时,不执行任何操作;

llen key

返回列表key的长度

ltrim key start stop

对一个列表进行修剪,让列表只返回指定区间内的元素,不存在指定区间内的都将被移除

rpoplpush source destination

(1).在一个原子操作内,执行两个动作:(2).将列表source的最后一个元素弹出并返回给客户端;(3).将source弹出的元素作为destination列表的头元素,插入到列表desination;

>>> Set:无序、元素不可重复

命令

描述

sadd key number [member ...]

将一个或多个member元素加入到key中,已存在于集合的member将被忽略(set元素不可重复)

scard key

返回key对应集合中的元素数量

sinter key [key ...]

返回一个集合的全部成员,该集合是第一个Key对应的集合和后面key对应的集合的交集

sinter destination key [key ...]

求两个集合的交集,将结果保存到destination集合,如果destination已存在,则覆盖,此处注意destination可以是key本身

sdiff key [key ...]

返回一个集合的全部成员,该集合是第一个Key对应的集合和后面key对应的集合的差集

sdiffstore destionation key [key ...]

求两个集合的差集,将结果保存到destination集合,如果destination已存在,则覆盖,此处注意destination可以是key本身

sunion key [key ...]

返回一个集合的全部成员,该集合是第一个Key对应的集合和后面key对应的集合的并集

sunion destination key [key ...]

求两个集合的并集,将结果保存到destination集合,如果destination已存在,则覆盖,此处注意destination可以是key本身

sismember key member

判断member元素是否key的成员,0表示不是,1表示是;

smembers key

返回集合key中的所有成员

smove source desination member

(1).原子性地将member元素从source集合移动到destination集合;(2).source集合中不包含member元素,smove命令不执行任何操作,仅返回0;(3).destination中已包含member元素,smove命令只是简单做source集合的member元素移除;

spop key [count]

(1).如果count不指定,移除并返回集合中的一个随机元素;(2).count为正数且小于集合元素数量,那么移除并且返回一个含count个元素的数组;(3).count为正数且大于等于集合元素数量,那么返回整个集合;

srandmember key [count]

类似pop,但仅仅是返回count个元素,不会把元素从集合中移除;

srem key member [member ...]

移除集合key中的一个或多个member元素,不存在的member将被忽略

>>> SortedSet:有序、元素不可重复

SortedSet中的每个元素都会关联一个整型或double型的分数(score),Redis正是通过分数(score)来为集合中的成员进行从小到大的排序(Redis SortedSet默认从小到大排序)。SortedSet的成员是不可重复的,但分数(score)却可以重复,在score相同的情况下,SortedSet会使用字典排序。

SortedSet是通过哈希表实现的,但在Redis SortedSet里面当items内容大于64时,同时使用了hash和skiplist。

命令

描述

zadd key score member [score member...]

(1).将一个或多个member及其score值加入有序集key中;(2).如果member已经是有序集的成员,那么更新member对应的score并重新插入member,保证member在正确的位置上

zcard key

返回有序集key中元素的个数

zcount key min max

返回有序集key中,score在[min,max]之间的元素数量

zrange key start stop [withscores]

(1).有序集成员按照score从小到大排序(如果想要从大到小排序,则使用zrevrange命令),具有相同score值的成员按字典序排列;(2).返回排序后的集合中指定下标区间内的成员;(3).下标参数start和stop都以0为底,也可以用负数,-1表示最后一个成员,-2表示倒数第二个成员;(4).可通过withscores选项让成员和它的score值一并返回;

zrank key number

(1).返回有序集key中成员member的排名,有序集默认按score值从小到大排列,如果想要从大到小,可使用zremrank命令。(2).名次从0开始;(3).此处注意,对于有序集:1 1 2 3,由于有两个1,因此3正序的Rank应当为2(以0为下标),但实际上会是3;

zrem key member [member ...]

移除有序集key中的一个或多个成员,不存在的成员将被忽略

zremrangebyrank key start stop

移除有序集key中指定排名区间内的成员

zremrangebyscore key min max

移除有序集key中,所有score值在[min,max]之间的成员;

>>> Redis key相关的命令

命令

描述

del key [key ...]

删除一个或多个指定的key,不存在的key将被忽略;

exists key

检查指定的key是否存在;

expire key seconds

为指定key设置生存时间,单位s

pexpire key millisecond

为指定key设置生存时间,单位ms

expireat key timestamp

为指定key设置生存时间,时间戳,单位s

keys pattern

查找所有符合给定模式pattern的key,如:(1).keys *:匹配所有key(2).keys h?llo:匹配hello、hallo、hxllo等(3).keys h*llo:匹配hllo、heeeeello等(4).keys h[ae]llo:匹配hello和hallo注意:虽然keys命令速度非常快,但是当Redis中有百万、千万甚至过亿数据的时候,扫描所有Redis的Key,速度仍然会下降,而由于Redis是单线程模型,所以势必将导致后面的命令阻塞直到KEYS命令执行完成。因此当Redis中存储的数据达到了一定量级(经验值10W以上就值得注意了)的时候,必须警惕KEYS造成Redis整体性能的下降。对 Redis 稍微有点使用经验的人都知道线上是不能执行 keys * 相关命令的,虽然其模糊匹配功能使用非常方便也很强大,在小数据量情况下使用没什么问题,数据量大会导致 Redis 锁住及 CPU 飙升,在生产环境建议禁用或者重命名!

migrate host port key destination-dbtimeout [COPY] [REPLACE]

(1).将 key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功, key会出现在目标实例上,而当前实例上的 key会被删除。(2).这个命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到迁移成功、迁移失败或等待超时。(3).命令的内部实现是这样的:它在当前实例对给定 key 执行 DUMP 命令 ,将它序列化,然后传送到目标实例,目标实例再使用 RESTORE 对数据进行反序列化,并将反序列化所得的数据添加到数据库中;当前实例就像目标实例的客户端那样,只要看到 RESTORE 命令返回 OK ,它就会调用DEL删除自己数据库上的 key 。(4).timeout 参数以毫秒为格式,指定当前实例和目标实例进行沟通的最大间隔时间。这说明操作并不一定要在 timeout 毫秒内完成,只是说数据传送的时间不能超过timeout。

move key db

当满足条件"当前数据库存在指定key,目的数据库不存在指定key"时,将当前数据库的 key 移动到指定的数据库 db 当中;移动完成后,当前数据库不存在key,目的数据库存在key;

persist key

移除指定key的生效时间,变为永久存活;

randomkey

从当前数据库随机返回而不删除一个key;

rename key newkey

(1).将key重命名为newkey(2).当key和newkey相同或key不存在时报错(3).如果newkey已存在,将覆盖旧值

ttl key

返回指定key的剩余存活时间,单位s;

pttl key

返回指定key的剩余存活时间,单位ms;

type key

返回key所存储的值的类型;

>>> Redis 更多命令

http://www.cnblogs.com/xrq730/p/8944539.html

四、Redis多数据库

Redis是一个字典结构的存储服务器,一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中,所谓字典就是我们所说的一个redis数据库。每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。

Redis支持多个数据库,每个数据库对外都是以一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过修改配置文件的databases属性来设置。

这就像在一个关系数据库实例中可以创建多个数据库类似。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要切换到1号数据库:

redis> select 1

ok

redis [1] > get felix

(nil)

然而这些以数字命名的数据库又与我们理解的数据库有所区别。首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么全部没有权限访问。

flushDB命令可以清空当前数据库的所有数据,flushAll命令会清空整个Redis实例中所有数据库的数据。综上所述,这些数据库更像是一种命名空间,而不适宜储不同应用程序的数据。

五、Redis数据的持久化

Redis支持两种数据持久化的方式:RDB和AOF。RDB是根据配置的规则定时将内存中的数据持久化到硬盘上,而AOF则是在每次执行写命令后将命令记录下来。

1、RDB

RDB持久化是通过快照的方式完成的,当满足配置规则(redis.conf文件)时,会将内存中的数据全量复制一份存储到硬盘上,这个过程称作”快照”。RDB文件是经过压缩处理的二进制文件,占用的空间较小。

(1).满足配置规则时自动快照

默认情况下,Redis会把快照数据存放在磁盘上的二进制文件中,文件名为dump.rdb,通过配置文件来设置Redis服务器dump快照的频率。打开redis.conf配置文件,找到如下配置属性:

#save后的第一个参数T是时间,单位是秒,第二个参数M是更改的键的个数;

#表示的含义是:当时间T内更新的键的个数大于M时,自动进行快照;

#各个条件之间是或的关系,只要满足其中一个就进行快照;

save 900 1

save 300 10

save 60 10000

#设置快照文件的名称

dbfilename dump.rdb

#指定快照文件的存储路径

dir ./

对于上面的配置不难看出,如果出现宕机断电等情况的话,RDB死有可能造成数据丢失的,比如save 300 10,如果在300s之内有9条key有更新时宕机,那么就造成了这9条更新key数据的丢失。

除了配置文件中配置的快照规则外,当执行save/bgsave命令、flushall命令、以及主从模式复制初始化时也会触发快照。

(1).save命令&bgsave命令

除了让Redis自动进行快照外,当我们需要重启、迁移、备份Redis时,我们也可以手动执行save或bgsave命令主动进行快照操作。

  • save命令:Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照以 RDB 文件的形式快照保存到磁盘,期间会阻塞所有来自客户端的请求;
  • bgsave命令: 这个命令与save命令的区别就在于该命令的快照操作是在后台异步进行的,进行快照操作的同时还能处理来自客户端的请求。执行bgsave命令后Redis服务端会马上返回OK表示开始进行快照操作,如果想知道快照操作是否已经完成,可以使用lastsave命令获取最后一次成功执行快照的时间,返回结果是一个Unix时间戳。

(2).flushall

当执行flushall命令时,Redis会清除redis实例中的所有数据。在执行flushall命令之前,只要redis.conf文件中设置的自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照条件时,执行flushall命令不会进行快照操作。

(3).执行复制

当设置了主从模式时,Redis会在复制初始化时自进行快照。

(4).快照原理

快照执行的过程如下:

> Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);

> 父进程继续处理来自客户端的请求,子进程开始将内存中的数据写入磁盘中的临时文件;

> 当子进程写完所有的数据后,再用临时文件替换老的RDB文件,至此,一次快照操作完成。

Redis启动时会自动读取RDB快照文件,将数据从硬盘载入到内存,根据数量的不同,这个过程持续的时间也不尽相同。

2、AOF

(1).AOF配置

Append Only File,只允许追加不允许改写的文件。AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍。

默认情况下,Redis没有开启AOF持久化功能,可以通过在配置文件中作如下配置启用:

#开启AOF持久化功能

appendonly yes

# 设置AOF文件名称,默认appendonly.aof

appendfilename "appendonly.aof"

#AOF文件的保存位置(和dump.db文件保存的位置一样,为同一个属性设置);

dir ./

appendfsync属性:

# appendfsync always

appendfsync everysec

# appendfsync no

在AOF模式下,执行的Redis命令会暂时先存放在缓冲区,再将缓冲区的的数据持久化到磁盘。

appendfsync属性表示调用fsync函数将数据持久化到磁盘的频率。当设置为no时,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统了;appendfsync everysec表示每秒同步一次;appendfsync always表示每一次写操作都会调用一次fsync。默认为appendfsync everysec。

(2).AOF文件重写

AOF是可识别的纯文本文件,它的内容就是一个个的Redis操作命令,每执行一条写命令,都会追加到AOF文件,所以AOF文件会变的越来越大。

为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能:Redis服务器可以创建一个新的AOF文件来替换现有的AOF文件,新旧两个文件所保存的数据状态是相同的,但是新的AOF文件不会包含任何浪费空间的冗余命令,通常体积会较旧AOF文件小很多。

手动触发命令:bgrewriteaof

即使 bgrewriteaof执行失败,也不会有任何数据丢失,因为旧的AOF文件在bgrewriteaof成功之前不会被修改。

据说从Redis 2.4开始,AOF重写由Redis自行触发, bgrewriteaof仅仅用于手动触发重写操作。但网上有说貌似redis还是没有自动触发bgrewriteaof,我们可以写个定时任务隔段时间去执行重写擦操作。

(3).Redis数据恢复

如果只配置RBD,启动时加载dump.rdb文件恢复数据;

如果只配置AOF,重启时加载AOF文件恢复数据;

如果同时配置了RBD和AOF,启动时只加载AOF文件恢复数据;

六、Redis的事务

Redis事务的本质是一次执行多条命令的集合,所有命令都保证顺序执行且不会被其它命令插入。将一组需要执行的命令放到multi和exec两个命令之间,multi命令代表事务开始,exec命令代表事务提交执行。

Redis事务相关的命令有:MULTI、EXEC、DISCARD、WATCH和UNWATCH。

MULTI:标记一个事务块的开始;

EXEC:执行所有事务块内的命令;

DISCARD:表示放弃执行事务;

WATCH:监视一个或多个key ,如果在事务执行之前所监视的key有过更新,那么事务执行将被打断;

UNWATCH:取消WATCH命令对所有key的监视;

一个Redis事务从开始到执行会经历以下三个阶段:

  • 开始事务
  • 命令入队
  • 执行事务

执行MULTI命令标志着事务开始,操作命令在执行EXEC 命令前被放入缓存队列,收到 EXEC 命令后开始顺序执行命令,在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

对于命令集错误:

(1).命令集中含有语法错误的,EXEC提交时所有命令均不会被执行;

(2).命令集中有命令发生运行时错误,那么正确的命令会正常执行,错误命令返回错误。所以Redis事务不保证原子性。

>下面我们看一下Redis事务的相关操作:

(1).正常操作

(2).取消事务

(3).WATCH监听

(4).执行错误

七、Redis主从复制(读写分离)、主从切换(一主二从三哨兵)

1、Redis主从复制(读写分离)

和MySQL一样,Redis支持主从同步,读写分离。假设有多台redis实例,一台作为主机Master,其他redis实例作为从机Slave,从机会定期的从主机上同步数据,进而达到主从数据同步。

读写分离,Master负责写请求,Slave负责读请求,这么做一方面通过将读请求分散到其他机器从而大大减少了master服务器的压力,另一方面slave专注于提供读服务从而提高了响应和读取速度。如果master宕机,slave可以介入并取代master的位置,以保证Redis能够正常提供服务。另外,一个Slave同样可以作其他redis实例的Master,即Redis支持一主多从或者多层级联结构。

(1).Redis主从的搭建配置

此处我们在一台Linux服务器上启动多个redis服务,模拟多个Redis实例。

> 新建目录

mkdir redis-cluster

> 将Redis安装目录copy三份到redis-cluster目录下并重命名如下

redis-master-6666

redis-slave-6667

redis-slave-6668

> 分别修改三服务的redis.config配置文件

a.port

6666/6667/6668

b.pidfile

pidfile /var/run/redis_6666.pid

pidfile /var/run/redis_6667.pid

pidfile /var/run/redis_6668.pid

c.dir

dir /usr/local/redis-cluster/redis-slave-6666

dir /usr/local/redis-cluster/redis-slave-6667

dir /usr/local/redis-cluster/redis-slave-6668

d.主机设置连接密码(修改主机的redis.conf文件)

requirepass 111111

也可以不配置,如果配置了,客户端或者从机在连接的时候就需要提供密码;

e.从机配置连接主机的密码(只修改从机的redis.conf配置文件)

masterauth 111111

f.主从复制的关键:指定Master,配从不配主(只修改从机的redis.conf文件)

slaveof 127.0.0.1 6666

> 启动三个redis服务,启动后如图

> 启动Master客户端,使用info replication命令查看master信息

> 分别启动Slave客户端,使用info replication命令查看slave信息

> 验证Master和Slave之间的数据同步,在Master中set几个key值,检验在Slave中是否能够获取到对应的key值

Matser-6666:

Slave-6667:

Slave-6668:

可以看到主机执行写命令,从机同步主机的值,主从复制成功。

2、主从切换(一主二从三哨兵)

我们想一下,在主从分离模式下,如果Master宕机了怎么办?显然,如果对Master宕机没有应对措施的话,那就尴尬了~

所以Redis提供了"sentinel(哨兵)",哨兵的作用就是监控redis主、从服务是否正常运行,如果Master出现故障,会自动将Slave转换为Master以保证Redis对外正常提供服务。所以哨兵的作用就是:

>监控主服务和从服务是否正常运行;

>Master出现故障时自动将Slave转换为Master;

(1).配置哨兵sentinel

查看redis的安装目录,会看到有个sentinel.cnf配置文件,分别对做如下配置:

> 分别修改端口为:

port 26379

port 26389

port 26399

> 如果想要配置sentinel在后台运行,可在sentinel.conf文件中加入如下配置:

daemonize yes

> 设置监控配置

sentinel monitor mymaster 127.0.0.1 6666 2

sentinel monitor mymaster 127.0.0.1 6666 2

sentinel monitor mymaster 127.0.0.1 6666 2

代表sentinel监控的master的名字叫做mymaster ,地址为127.0.0.1:6666,2代表当有2个sentinel主观的认为master已死时,master将会被客观的认为已死。

> 解释几个配置的含义

# sentinel down-after-milliseconds mymaster 30000

sentinel会向master发送心跳PING来确认master是否存活,如果master在down-after-milliseconds时间内(单位:毫秒)不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地认为这个master已经不可用了(SDOWN)。不过这个时候sentinel并不会马上进行主备切换,这个sentinel还需要参考其他sentinel的意见,如果超过quorum(法定人数)数量的sentinel也主观地认为该master死了,那么这个master就会被客观地认为已经死了(ODOWN),将会触发failover(失效备援)操作。

那么触发failover后马上就开始主从切换吗?不是的!

假设有5个sentinel,quorum(法定人数)被设置为2,当2个sentinel认为一个master已经不可用时,sentinel将会触发failover,但是,进行failover的那个sentinel必须获得至少3个sentinel(总哨兵的一半以上)的授权才可以真正执行主从切换操作。

# sentinel failover-timeout mymaster 180000

上面这个配置表示failover过期时间,表示触发failover后,在failover-timeout时间段内仍然没有真正执行failover主从切换操作, 那么此次failover失败。

> 启动sentinel

进入src,执行./redis-sentinel ../sentinel.conf 启动;

(2).验证主从切换

> 首先我们kill掉主服务

> 然后我们再去使用info replication查看之前的从机

我们发现,原先的slave-6668被切换为新master,新master-6668有一个slave,即6667,6667原本作为6666的slave,主从切换后作为新master-6668的slave。同时相关的redis.conf配置文件也被修改。

> 重启6666

当我们重启6666后,发现它作为了6668的slave。

八、Redis发布订阅

跟MQ的机制很类似。

发布者不直接发送消息给特定的订阅者,而是发布消息到不同的频道,订阅者可以订阅任意数量的频道,当有新消息发送给频道时, 这个消息就会被发送到订阅它的客户端。发布者和订阅者都是Redis客户端。

> 订阅频道

subscribe felixChat

> 发布消息到指定频道

publish redisChat 'Hello Redis'

> 退订频道

unsubscribe redisChat

九、Redis单线程模型

Redis服务端是单线程来处理命令的,所有到达服务端的命令都会进入一个队列,逐个执行,不会有两条命令被同时执行,不会产生并发问题,这就是Redis的单线程基本模型。

※ Redis是单线程来处理命令的,为什么能够达到每秒万级别的处理能力呢?

> 纯内存操作

> 单线程免去了创建维护线程的成本以及线程间切换开销

> redis使用了IO多路复用技术,可以让单个线程高效的处理多个连接请求

※IO多路复用简述

IO多路复用相比于多线程的优势在于系统的开销小,系统不必创建和维护线程,免去了线程切换带来的开销。这里"多路"指的是多个网络连接,"复用"指的是复用同一个线程。

IO多路复用就是利用select、poll、epoll监控多个流的 I/O事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态唤醒线程。其中select和poll是程序去轮询监控所有的流。而epoll是只轮询那些真正发出了事件的流,并且只依次顺序的处理准备就绪的流,这种做法就避免了大量的无用操作。

而select、poll、epoll都是IO多路复用的实现机制,Redis采用的就是epoll实现。

举例epoll:一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个大吼一声"倒酒"(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就这样一个服务员服务好多人,有时没人喝酒,服务员处于空闲状态,可以干点别的事比如玩玩手机。至于select和poll,需要你挨个去问要不要酒,就没时间玩手机了。

十、Redis批量执行命令

> 准备txt文件

将要执行的命令一行一行写进去,或者从其他文件拷贝进来。在批量插入数据时,我们可以写程序将原始数据构建为一行一行的redis命令,保存到该txt文件中。

> 转码(使用unix2dos命令)

redis-cli中只支持dos格式的换行符 \r\n ,所以你在linux、mac或windows下创建的文件,最好都转个码,没有转码的文件,执行会失败。

[root@JD ~]# cd /opt/

[root@JD opt]# ls

batchComand.txt

[root@JD opt]# unix2dos batchComand.txt

-bash: unix2dos: command not found

如果在转码时提示命令不存在,那么我们就需要安装unix2dos转码工具。

[root@JD opt]# yum install unix2dos

安装成功后再执行转码命令:

[root@JD opt]# unix2dos batchComand.txt

unix2dos: converting file batchComand.txt to DOS format ...

转码成功!

> 执行导入

[root@JD src]# cat /opt/batchComand.txt | /usr/local/redis/redis-4.0.10/src/redis-cli --pipe

All data transferred. Waiting for the last reply...

Last reply received from server.

errors: 0, replies: 4

如果要想导入远程主机,只需执行如下命令即可:

[root@JD src]#cat /opt/batchComand.txt | /usr/local/redis/redis-4.0.10/src/redis-cli -p 6666 -h 127.0.0.1 --pipe

All data transferred. Waiting for the last reply...

Last reply received from server.

errors: 0, replies: 4

十一、安全禁用或者重命名危险命令

对 Redis 稍微有点使用经验的人都知道线上是不能执行 keys * 命令的,虽然其模糊匹配功能使用方便也很强大,在小数据量情况下使用没什么问题,但数据量大会导致 Redis 锁住及 CPU 飙升,在生产环境建议禁用或者重命名!

1、Redis还有哪些危险命令

> keys

> flushdb

> flushall

> config:客户端可修改 Redis 配置

对于以上几个危险命令,在生产环境建议禁用或者重命名;

2、怎么禁用或重命名危险命令?

看下 redis.conf 默认配置文件,找到 SECURITY 区域,如图:

看说明,添加 rename-command 配置即可达到安全目的。

1)禁用命令

rename-command KEYS ""

rename-command FLUSHALL ""

rename-command FLUSHDB ""

rename-command CONFIG ""

2)重命名命令

rename-command KEYS "XXXXXXXXXXXX"

rename-command FLUSHALL "XXXXXXXXXXXX"

rename-command FLUSHDB "XXXXXXXXXXXX"

rename-command CONFIG "XXXXXXXXXXXX"

上面的 XX 可以定义新命令名称,或者用随机字符代替。经过以上的设置之后,危险命令就不会被客户端执行了。

本文分享自微信公众号 - 前端迷(love_frontend),作者:程序员耕耘

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 学习前端算法前你需要了解的‘大O表示法’

    在现实生活中,解决一个问题可以有多种方法,其中有好的方法,也有较为一般的方法。评判标准虽有不同,但总体思想是:用最小的代价获得最多的收益。

    前端迷
  • Virtual Dom和Diff算法

    这是一篇很长的文章!!!坚持看到最后有彩蛋哦!!! 文章开篇,我们先思考一个问题,大家都说 virtual dom 这,virtual dom 那的,那么 vi...

    前端迷
  • 小邵教你玩转ES6(一)-let,const和解构赋值

    这篇文章主要让你学会工作当中常用的es6技巧,以及扩展如实现数据双向绑定,class用es5如何实现、如何给伪数组添加迭代器等等。

    前端迷
  • Web-第二十天 Redis学习【悟空教程】

    rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.66.1.13.0.el6.i686

    奋斗蒙
  • 新手村:Redis 基础补充知识

    新手村的第一篇文章(新手村:最适合新手的 Redis 基础)是村民的处女作,在之后的学习中回看这篇文章,觉得有一些纰漏之处,甚是惭愧,这也是本篇文章的由来和内容...

    syy
  • Java程序员,想要彻底弄懂Redis,这15点你一定要明白~(纯干货)

    Redis是一款开源的、高性能的键-值存储(key-value store)。它常被称作是一款数据结构服务器(data structure server)。

    秃顶的Java程序员
  • NoSQL篇 | NoSQL从小白到码神 之 Redis篇

    课程目录: - NoSQL背景 - NoSQL简介 - NoSQL和关系型数据库对比 - Redis简介 - Redis下载安装配置(Linux环境) - R...

    码神联盟
  • 新手村:最适合新手的 Redis 基础

    简而言之,Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种数据类型,...

    syy
  • python-Redis模块常用的方法汇总

    小小咸鱼YwY
  • 关于 Redis 的一些新特性、使用建议和最佳实践

    redis从2009年诞生到现在已经走过将近10年,从最开始大家在讨论nosql和传统关系数据库孰优孰劣,到现在大家谈起分布式锁,缓存纷纷将Redis作为其第一...

    芋道源码

扫码关注云+社区

领取腾讯云代金券