了解Redis前先来了解一些基本的概念:
同步和异步、阻塞和非阻塞
同步
:所谓同步,就是在C端发出一个功能调用时,在没有得到结果之前,该调用就不返回。
异步
:异步的概念和同步相对,当C端一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
阻塞
:阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,即线程暂停运行)。函数只有在得到结果之后才会返回。
非阻塞
:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
原子操作和二进制安全
原子操作
:不可中断的一个或一系列操作。就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,这里的原子实际是使用了物理学里的物质微粒的概念。
二进制安全
:二进制安全的含义比较多,这里与redis挂钩的主要是基于C语言中的字符串处理来区分;C语言中字符串必须符合某种编码(比如ASCII)规范,并且除了字符串的末尾之外,字符串里面不能包含空字符(\0
),否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。这样在处理二进制数据时可能会导致数据的变化。简单点来理解二进制安全,就是指字符串中可以在任意位置出现空字符而不会出现上述C语言中字符串处理规则所导致的问题。
一、Redis介绍
一般介绍Redis都会找同类型的Memcache来做对标,Redis与Memcache相似却比Memcache更为强悍;Redis的字面含义源于英文:Remote Dictionary Server,远程Remote的Re,字典Dictionary的Di,服务器Server的S就构成了Redis的名称来源。
Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库
、缓存
和消息中间件
。 它支持多种类型的数据结构,包含5种常用的字符串(String
)、 散列(Hash
)、 列表(List
)、 集合(Set
)、 有序集合(Sorted Set
) 。换一种说法:Redis是一个充分利用内存的NoSQL数据库,即非关系型数据库。
Redis内置了复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions)和不同级别的磁盘持久化,并通过灵活的集群解决方案、主从配置(Master-Cluster)提供高可用性。
Redis常见的5种数据类型都支持push/pop
、add/remove
及取交集、并集和差集及其他更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作追加写入到记录文件。当然这种将数据从内存回写至硬盘的功能也是可配的,可以选择关闭。
二、Redis的数据类型
1、String
二进制安全的字符串类型,是Key-Value系统的最基本类型,String类型可以存储任何形式的字符串,当然保存数字也是不在话下,由数字构成的字符串嘛。
1.1、设置key-value:SET key value [EX seconds] [PX milliseconds] [NX|XX]
SET命令是不区分大小写的,与SQL命令类似统一某一种规则会避免不少麻烦。SET命令的作用是:将键key设定为指定的“字符串”值。如果 key 已经保存了一个值,那么这个操作会直接覆盖原来的值,并且忽略原始类型。当SET命令执行成功之后,之前设置的过期时间都将失效。
SET命令成功返回ok
,失败返回特殊错误值nil
从redis2.6.12版本开始,SET命令增加了一系列选项:
- EX seconds – 设置键key的过期时间,单位:秒
- PX milliseconds – 设置键key的过期时间,单位:毫秒
- NX – 只有键key不存在的时候才会设置key的值;记忆技巧:N--not,X--exists中的x
- XX – 只有键key存在的时候才会设置key的值
由于SET命令加上选项已经可以完全取代SETNX,SETEX,PSETEX的功能,所以在将来的版本中,redis可能会不推荐使用并且最终抛弃这几个命令。
1.2、通过key获取value:GET key
GET命令执行后可以返回key的value;如果key不存在,返回特殊值nil;如果key的value不是string,就返回错误,因为GET获取string类型的value。
1.3、原子操作步增、步减key对应的整数类型value:INCR
、DECR
、INCRBY
、DECRBY
INCR key
将key对应的整数值步增1,即key对应的整数值value加1并返回步增之后的值;
DECR key
将key对应的整数值步减1,即key对应的整数值value减1并返回步减之后的值;
INCRBY key increment
将key对应的整数值步增increment,即key对应的整数值value加increment并返回步增之后的值,increment必须是整数;
DECRBY key increment
将key对应的整数值步减increment,即key对应的整数值value减increment并返回步减之后的值,increment必须是整数;
上述4个命令中,若key对应的value不是一个整数值(即Interger),命令将返回(error) ERR value is not an integer or out of range
的错误。
还是特别啰嗦一下:上述整数的含义包含正整数、负整数和0
1.4、其他操作命令
步增指定的双精度小数:incrbyfloat key increment
获取字符串长度:strlen key
往字符串尾部追加内容:append key value
获取字符串的某一段内容:getrange key start end
,getrange命令是被改写过的,在2.0版本之前叫做substr
设置字符串的某一段内容:setrange key offset value
设置及获取字符串的某一位(bit):setbit/getbit
批量获取一系列字符串的内容:mset key1 value1 [key2 value2 ...]
和mget key1 [key2 ...]
2、Hash
Redis hash是一个string类型的field和value的映射表;一个key可对应多个field,一个field对应一个value。
设置key指定的哈希集中指定字段的值:HSET key field value
此时key代表的是一个哈希集的名称,field代表了属性名,而value代表了属性值;key指定的哈希集可以存放一些列的field-value键值对。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与key关联;如果字段在哈希集中存在,它将被重写。
返回值:1如果field是一个新的字段,0如果field已存在并被重写。
获取key指定的哈希集中的值:HGET key field
和 HGETALL key
HGET获取指定哈希集下的字段对应的值,返回key指定的哈希集中filed字段所关联的值,若存在field则返回其值,若key或field不存在则返回特殊错误值nil
HGETALL则返回由key指定的整个哈希集内的所有键和值,返回结果中返回值中,每个字段名的下一个是它的值,所以返回值的长度是哈希集大小的两倍,若按PHP数组的看法来理解,则返回值是所有键和所有值构成的索引数组,该索引数组第一个是键名,第二个是第一个键名对应的值,第三个是另外一个键名,第四个是另外一个值,以此类推;若key存在则返回key下的所有键值对,若key不存在则返回空列表。
与String类型的相关命令差不多,还有如下命令:
HMSET key field value [field value ...]
:批量设置filed-value
HMGET key field [field ...]
:批量获取key指定的哈希表中的多个filed的值
HLEN key
:获取key指定的哈希表的字段数量(字段长度)
HDEL key field [field ...]
:删除key指定的哈希表中的filed字段
HKEYS key
:获取key指定的哈希表中的所有filed字段
HSTRLEN key field
:获取key指定的哈希表中filed对应的值的字符串长度
HEXISTS key field
:判断key指定的哈希表中是否存在field这个字段
HINCRBY key field increment
:上述String中的有关步增或步减的命令incr、decr以及incry by、decrby实际上在redis内部是同一个命令;对于哈希表,是不存在hdecrby这个命令的,实现redis的hash字段值的步增或步减均有hincrby命令实现,通过指定不同的increment即可(正数实现步增、负数实现步减,数字大小实现步伐间隔)。同理还有HINCRBYFLOAT key field increment
命令。
3、List
List是一个链表,或者更为简单的理解就是一个非常灵活的队列。
链表是分左右的,所以对List链表操作的命令也会区分左端操作还是右端操作,队列无非进队列和出队列,以及进或出队列时的特性。关于链表的左右、头尾的区别:按照汉语书写习惯从左至右,左侧为链表头(左),右侧为链表尾(右)。
LPUSH key value [value ...]
:将所有指定的值插入到链表key的列表的头部(左侧)。如果 key 不存在,那么在进行push操作前会(自动)创建一个空列表。 如果 key 对应的值不是一个list的话,那么会返回一个错误。可以使用一个命令把多个元素push进入列表,只需在命令末尾加上多个指定的多个待插入的元素值即可。元素是从最左端的到最右端的、一个接一个被插入到list的头部。 所以对于这个命令LPUSH mylist a b c
,返回的列表是c为第一个元素, b为第二个元素, a为第三个元素。命令执行成功后返回链表的长度。
LPOP key
:移除并且返回key对应的list的第一个元素,即从队列左侧或者说队列头弹出元素---队列头部出。当key存在时返回队列左侧或头部的第一个元素,当key不存在时返回特殊错误值nil
类似的也有从队列右侧或者说队列尾进元素和出元素的方法,功能与lpush、lpop类似,不再详细介绍:RPUSH key value [value ...]
、RPOP key
LLEN key
:返回存储在 key 里的list的长度。 如果 key 不存在,那么就被看作是空list,并且返回长度为 0。 当存储在 key 里的值不是一个list的话,会返回error。
LREM key count value
:从存于 key 的列表里移除前count次出现的值为value的元素。 这个count参数通过下面几种方式影响这个操作:
- count > 0: 从头往尾移除值为 value 的元素;
- count < 0: 从尾往头移除值为 value 的元素;
- count = 0: 移除所有值为 value 的元素;
比如, LREM list -2 hello
会从存于 list 的列表里移除最后两个出现的“hello”。需要注意的是,如果list里没有存在key就会被当作空list处理,所以当 key不存在的时候,这个命令会返回0。此命令执行成功则返回被移除的元素个数。
LINSERT key BEFORE|AFTER pivot value
:把value插入存于key的列表中在基准值pivot的前面或后面。当key不存在时,这个list会被看作是空list,任何操作都不会发生。当key存在,但保存的不是一个list的时候,会返回error。其中pivot是链表中已存在的元素值,命令执行成功返回经过插入操作后的list长度,或者当 pivot 值找不到的时候返回-1
LSET key index value
:设置(修改)index位置的list元素的值为value。 更多关于 index 参数的信息,详见下方LINDEX命令的说明。当index超出范围时会返回一个error。
LINDEX key index
:返回列表里的元素的索引index存储在key里面。下标是从0开始索引的,所以0是表示第一个元素, 1 示第二个元素,并以此类推。 负数索引用于指定从列表尾部开始索引的元素。在这种方法下,-1表示最后一个元素,-2表示倒数第二个元素,并以此往前推。当key位置的值不是一个列表的时候,会返回一个error。需要特别说明的是lindex的行为并不与lpop或rpop相同,lindex命令执行后并不会删除队列中的元素,见下图。
当然与setx需要满足key存在的条件才设置值的条件类似,还有:LPUSHX key value
、RPUSHX key value
,以及LPOP、RPOP的阻塞版本:BLPOP key [key ...] timeout
、BRPOP key [key ...] timeout
4、Set
在Redis中,可以将Set类型看作为没有排序的、没有重复元素的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。
和List类型不同的是,Set集合中不允许出现重复的元素,这一点和C++标准库中的set容器是完全相同的。换句话说,如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。
集合操纵命令
SADD key member [member ...]
:添加一个或多个指定的member元素到集合的key中。指定的一个或者多个元素member如果已经在集合key中存在则忽略.如果集合key不存在,则新建集合key,并添加member元素到集合key中。如果key的类型不是集合则返回错误。命令执行成功后返回成功添加到集合里元素的数量,不包括已经存在于集合中的元素。
SREM key member [member ...]
:在key集合中移除指定的元素member,此处member是元素的值。如果指定的元素不是key集合中的元素则忽略 如果key集合不存在则被视为一个空的集合,该命令返回0;如果key的类型不是一个集合,则返回错误。命令执行成功后返回从集合中移除元素的个数,不包括不存在的成员。
SCARD key
:返回集合key中的元素个数,若key不存在则返回0
SMEMBERS key
:返回key集合所有的元素;该命令的作用与使用一个参数的SINTER命令作用相同。sinter是一个或多个集合运算的命令,关于集合之间的运算相关命令,详见下方。
SPOP key [count]
:删除并返回集合key中一个或多个元素,指定count则随机返回count个元素并从集合key中删除返回的这些元素,若没有显式指定count,则count默认值为1;鄙人在redis3.0.4版本上试验得知:count的取值必须是1至key集合中元素的总个数,其他取值例如0或负数则会出现一个error,这一点与srandmember命令有区别。这个命令引入的比较晚,请留意redis版本。
SRANDMEMBER key [count]
:与spop命令的行为差不多,唯一的区别就是sranmember命令随机返回count个元素后并不会从集合key中删除返回的这些元素。此命令返回含有count个不同的元素的数组,如果count是个整数且大于集合中元素的个数时,则返回整个集合的所有元素;当count是负数,则会返回一个包含count的绝对值的个数元素的数组,如果count的绝对值大于元素的个数,则返回的结果集里会出现某一个元素重复的情况。
集合运算命令
先来几个数学概念:
空集
:不含任何元素的集合称为空集。空集的性质:空集是一切集合的子集。空集是任何非空集合的真子集。
差集
:一般地,记A,B是两个集合,则所有属于A且不属于B的元素构成的集合,叫做集合A减集合B(或集合A与集合B之差),类似地,对于集合A、B,我们把集合{x∣x∈A,且x∉B}叫做A与B的差集。
交集
:设A、B是两个集合,由所有属于集合A且属于集合B的元素所组成的元素,叫做子集A与集合B的交集(intersection),记作A∩B;读作“A与B的交集”。
并集
:若A和B是集合,则A和B并集是有所有A的元素和所有B的元素,而没有其他元素的集合。A和B的并集通常写作 "A∪B",读作“A并B”
SDIFF key [key ...]
:运算一个集合和给定的一个或多个集合的差集。不存在的key在之心sdiff命令时被认为是一个空集,多个集合执行差集运算规则:dfiff key key1 key2
,则key和key1执行差集运算返回的结果集再和key2执行差集运算并返回结果。若只给定一个参数,则相当于该一个参数与空集执行差集运算,与smembers命令效果一致。
在sdiff的基础上可以将取差集的结果存储到另外一个集合中的命令:SDIFFSTORE destination key [key ...]
,其中destination即为存储取差集结果的新集合;注意此命令并不返回差集的结果,而是将结果存在destionation中,当然该命令有返回值,返回值即为差集运算结果集的元素个数。
SINTER key [key ...]
:返回给定的所有的集合的成员的交集。若sinter命令仅给出一个参数,则与smenber命令效果一致,返回该一个参数指定的集合中的所有元素,一个参数的sinter可以认为是这一个参数指定的集合与空集执行交集运算的结果;若key不存在则在运算时被认作空集。
与sdiffstrore命令类型,也有SINTERSTORE destination key [key ...]
命令,不再详述。
SUNION key [key ...]
:返回给定的多个集合的并集中的所有成员。
当然啦,还有与sdiffstore、sinterstore类似的SUNIONSTORE destination key [key ...]
命令,不再赘述。
5、Sorted Set
Redis的有序集合,即sorted set;sorted set在set的基础上,增加了排序属性,可以认为sorted set是set的升级版。
有序集的操纵
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
:将一个或多个member元素及其score值加入到有序集key当中;返回值为被添加的新元素个数。如果key不存在,则创建一个空的有序集并执行ZADD操作。当key存在但不是有序集类型时,返回一个错误。
其中NX|XX属性参数与String类型中set命令的意思一致,即NX不存在时添加,XX存在时添加;CH是change单词的一个缩写,CH属性是用于约束返回值的,加上CH属性后zadd命令的返回值仅计算以下两种情况:1、全新的元素,2、已存在的元素但score值进行了修改。若不加CH属性,zadd命令返回的数字仅包含新元素,不包含那些更新的、已存在的元素。当加上INCR属性时,zadd命令表现出来的功能就与ZINCRBY类似,而且加上INCR属性后,zadd命令一次只能添加(或修改)一个元素,当处于添加情况时,直接添加这个新元素,新元素的score值为参数中的score;当处于修改情况时,加入INCR属性后score值并不是直接进行替换修改,而是将原先的score值加上新指定score值之后进行替换修改;加上INCR属性后,返回值会变成这个元素的字符串形式的新score值。NX|XX、CH、INCR属性是Redis3.0.2版本之后新增的。Redis2.4版本以前,ZADD命令每次只能添加一个元素。
ZADD命令执行规则:如果某个member已经是有序集的成员,那么更新这个member的score值,并通过重新插入这个member元素,来保证该member在正确的位置上。若添加的元素已存在,且score值一致,将不做改变,若这种情况一次只添加了一个元素则返回值为0
score值用于Sorted Set内部的排序,排序规则为:按score值从小到大的排序(ASC)。score值可以是整数值或双精度浮点数,redis内部使用64比特的单精度类型值来处理这个排序分数score,score正负数均可,多个元素的score值允许重复,若多个元素具有相同的score值,则排序规则是按照元素值的字典顺序排序的。
ZINCRBY key increment member
:为有序集key的成员member的score值加上增量increment后作为新的score值对该member进行修改。如果key中不存在member,就在key中添加一个member,score是increment(就好像它之前的score是0.0)。如果key不存在,就创建一个只含有指定member成员的有序集合。当key不是有序集类型时,返回一个错误。score值必须是字符串表示的整数值或双精度浮点数,并且能接受double精度的浮点数。也可以给一个负数来减少score的值。
ZREM key member [member ...]
:删除有序集中一个或多个member,返回删除的有序集的个数,当key存在但不是有序集时返回一个error
ZREMRANGEBYRANK key start stop
:按下标索引删除有序集中的元素;下标参数start和stop都以0为底,0处是分数最小的那个元素。这些索引也可是负数,表示位移从最高分处开始数。有序集中有关start、stop两个参数的含义处理,与php中substr函数string substr ( string $string , int $start [, int $length ] )
的第二个参数非常类似,可以借鉴理解。
ZSCORE key member
:返回有序集key中,成员member的score值。如果member元素不是有序集key的成员,或key不存在,返回nil。
ZRANK key member
:返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。排名以0为底,也就是说,score值最小的成员排名为0。使用ZREVRANK命令可以获得成员按score值递减(从大到小)排列的排名。
ZREVRANK key member
:返回有序集key中成员member的排名,其中有序集成员按score值从大到小排列。排名以0为底,也就是说,score值最大的成员排名为0。与zrank命令仅排序上的差异,一个是ASC一个是DESC。
ZCARD key
:返回key的有序集元素个数。返回key的有序集元素个数。
ZCOUNT key min max
:返回有序集key中,score值在min和max之间(默认包括score值等于min和max)的成员。返回值为指定分数score范围内的元素个数。
ZRANGE key start stop [WITHSCORES]
:返回有序集key中从索引start开始到索引stop结束的所有元素,并且包含start和stop位置的元素,其中start和stop取值规则为:0表示有序集中的第一个元素,1则表示第二元素,以此类推;若是负数则是相反位置的元素,例如-1表示最后一个元素,-2表示倒数第二个元素,以此类推。start和stop的取值超出范围的话并不会出现错误,若start大于等于该有序集的总元素个数,或者start大于stop则返回空集;若果stop大于该有续集的总元素个数,那么将返回从start位置开始的之后的所有元素。
如果加上WITHSCORES选项,返回值中将包含各个元素的score值。加上WITHSCORES属性后返回值的格式为:value1,score1,...,valueN,scoreN
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
:返回key的有序集合中的分数在min和max之间的所有元素(包括分数等于max或者min的元素,如果不想包括边界值,可以使用诸如(min和(max来表示)。可选的LIMIT参数指定返回结果的数量及区间(类似SQL中SELECT LIMIT offset, count)。注意,如果offset太大,定位offset就可能遍历整个有序集合,这会增加O(N)的复杂度。
zrange和zrangebyscore的区别通过名称就一目了然,前者依据排序索引取区间,后者通过score分数值取区间。
有序集的运算
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [SUM|MIN|MAX]
:有序集的交集运算。
计算给定的numkeys个有序集合的交集,并且把结果放到destination中。 在给定要计算的key和其它参数之前,必须先给定需要执行交集运算的key的个数(numberkeys)。默认情况下,交集运算的结果中一个元素的分数是参与交集运算的有序集合中该元素分数之和,前提是该元素在这些有序集合中都存在。返回值为交集运算结果集的元素个数。
[WEIGHTS weight]
参数,你可以为每个给定的有序集指定一个乘法因子,即每个参与交集运算的有序集中的所有成员的score值在传递给聚合函数之前都要先乘以该因子,WEIGHTS为关键字,其后跟随每个参与交集运算的乘法因子,多个因子使用空格分开。如果WEIGHTS没有给定,默认就是1。
[SUM|MIN|MAX]
参数,默认值为SUM,也就是前述提到的交集运算的结果集中每个元素的分数score值是如何运算而来。MIN取多个参与运算的有序集中相同元素的score值中最小的一个,MAX以此类推。
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [SUM|MIN|MAX]
:有序集的并集运算。
计算给定的numkeys个有序集合的并集,并且把结果放到destination中。在给定要计算的key和其它参数之前,必须先给定key个数(numberkeys)。 默认情况下,结果集中某个成员的score值是所有给定集下该成员score值之和。返回值为并集运算结果集中的元素个数。
参数[WEIGHTS weight]和[SUM|MIN|MAX]与取交集命令中的参数含义一致,不再赘述。
redis的Sorted Set有序集运算命令中暂时没有取差集的命令。
三、Linux上Redis的配置安装和要点
Redis编译安装很简单,因为makefile在提供的源码包中早已写好,所以没有了传统的繁琐的configure步骤,进入源码直接make && make install
即可。
1、Redis的安装配置
当前Redis的稳定版本是3.2.0,就以该版本为例;试验机器是centos6.5 x86_64,Redis编译后可执行文件放置在/usr/local/redis/bin目录下,配置文件放置在/usr/local/redis/conf目录下;源码包目录为/usr/local/src
编译、测试Redis可执行文件
##创建redis可执行文件的目录 mkdir -p /usr/local/redis/bin mkdir -p /usr/local/redis/conf ##进入源码包目录,便于源码包和源码解压后的源码管理 cd /usr/local/src ##下载redis3.2.0版 wget https://download.redis.io/releases/redis-3.2.0.tar.gz ##解压源码包并进入源码目录 tar zxvf redis-3.2.0.tar.gz cd redis-3.2.0 ##编译 #make完毕会提示“Hint: It's a good idea to run 'make test' ;)” make ##可选的redis测试 与php编译安装时执行make test月莫一个意思 ##要执行make test命令需要安装tcl库--不是那个卖电视的TCL的 ##直接yum安装,若提示找不到相关rpm包,则需要安装下yum的拓展epel yum install epel-release ##可选 yum install tcl tcl-devel ##测试redis 可选 make test
这一步骤没什么需要说明的。
Redis可执行文件移动和Redis配置
上一步编译完毕后,没有了常规的make install命令,那么编译完成后的可执行文件在什么地方呢?
make命令执行完毕后,所有redis的可执行文件均会在源码包目录的下的src目录下产生,该scr目录下原先存在着一些c代码文件、头文件,都是在正式使用Redis时不再需要的;redis的可执行文件为:redis-benchmark
、redis-check-rdb
、redis-sentinel
、redis-check-aof
、redis-cli
、redis-server
。
##移动Redis可执行文件 mv /usr/local/src/redis-3.2.0/scr /usr/local/redis/bin #瘦身Redis可执行文件目录 rm -rf /usr/local/redis/bin/*.c rm -rf /usr/local/redis/bin/*.o rm -rf /usr/local/redis/bin/*.h rm -rf /usr/local/redis/bin/Makefile* rm -rf /usr/local/redis/bin/*.sup ##其中mkreleasehdr.sh和redis-trib.rb文件也可以删了 ##复制redis配置文件 cp /usr/local/src/redis-3.2.0/redis.conf /usr/local/redis/conf/redis.conf
redis配置文件修改配置
Redis的主要配置项和含义如下:
daemonize:是否以后台daemon方式运行
bind:绑定ip,Redis服务对公网开放是存在危险的,默认是绑定到本机127.0.0.1的不对公网开放
protected-mode:保护模式是否开启,当保护模式开启后Redis仅接受本机ipv4的127.0.0.1、ipv6的::1以及通过Unix socket方式连接。此项配置与bind相互搭配,用以提高Redis的安全性。
pidfile:pid文件位置
port:监听的端口号,Redis的端口号为6379,这儿Redis的作者提到为何选6379端口的缘由:MERZ
timeout:客户端请求超时时间,0的话不限制
loglevel:log信息级别
logfile:log文件位置,可选值:debug|verbose|notice|warning
databases:开启数据库的数量
save * *:保存快照的频率,第一个*表示多长时间,第二个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
rdbcompression:是否使用压缩
dbfilename:数据快照文件名(只是文件名,不包括目录)
dir:数据快照的保存目录(这个是目录)
appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)
maxclients:最大同时可连接客户端数目,默认是10000;当客户端连接的总数超过这个值时,新客户端尝试连接将收到error消息。
requirepass:设置连接Redis时需要输入的密码;Redis的并发能力非常强大,设置的密码然并卵。
##redis配置 vi /usr/local/redis/conf/redis.conf ###找到127行的 daemonize no #修改为: daemonize yes #行数可能会变化,daemonize是守护进程的意思,即开启redis守护进程 ##可选的关闭持久化,也就是关闭redis将数据回写至硬盘的功能 ##找到201至203行如下内容注释掉,取消199行的注释 --- #save 900 1 #save 300 10 #save 60 10000
2、CentOS下Redis的服务管理脚本
留意下述脚本中的相关路径,配合Redis的配置文件中的相关配置项进行修改,例如pid文件、配置文件路径、redis-server可执行文件等。
vi /etc/init.d/redis-server #新建redis服务管理文件 写入如下内容 ------ #!/bin/sh # # redis script starts and stops the redis daemon # By www.JJonline.Cn # chkconfig:- 85 15 # description: redis is an key-value RAM NOSQL DB \ # processname: redis # config: /usr/local/redis/conf/redis.conf # pidfile: /data/pid/redis.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 #sbin name redis="/usr/local/redis/bin/redis-server" #configure file name config=/usr/local/redis/conf/redis.conf prog=$(basename $redis) #lockfile lockfile=/var/lock/subsys/redis #service start pidfile=${PIDFILE-/data/pid/redis.pid} start(){ [ -x $redis ] || exit 5 echo -n $"Starting $prog: " daemon --pidfile ${pidfile} $redis $config retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } #service stop stop(){ echo -n $"Stopping $prog: " killproc -p ${pidfile} $redis retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } #service restart restart(){ stop sleep 1 start } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) #rh_status_q && exit 0 $1 ;; stop) #rh_status_q && exit 0 $1 ;; restart) $1 ;; status) rh_status ;; *) echo $"Usage: $0 {start|stop|status|restart}" exit 2 esac
保存、授予执行权限,即可使用service redis-server start|stop|restart
命令来方便管理redis了,还可以使用chkconfig redis-server on
将redis设置成开机启动。
3、Redis的主从配置要点
以2台Redis Server为例做下概要
先做一个最简单的Redis主从实验:两台Redis配置一摸一样,选定好一台作为主(Master),另外一台作为从(Slave),将Slave的配置文件中的slaveof配置项打开(去掉注释),并填入Master的IP地址和端口号,重启Slave的Redis进程,一个极度简单的master-slave主从就完成了。也可以在同一台机器上,启动多个Redis实例,多个实例之间使用不同的配置文件实现主从测试。
生产环境主从配置不会如此简单。Redis的主从复制区分全量复制和增量复制。
Redis主从实现机制
Slave的Redis在接收到“slaveof ip port”命令以后,首先会将自身的状态置为REDIS_REPL_CONNECT,表示需要与自己的Master连接,此时Slave并没有与Master做连接。Redis每隔100ms会调用serverCron()函数一次,每10次serverCron()的调用会调用replicationCron()一次,即每1s会调用一次replication()函数。在replication()函数中,会检查Slave的状态,如果是处于REDIS_REPL_CONNECT状态,就会建立syncWithMaster()的事件处理函数,并将Slave的状态改成REDIS_REPL_CONNECTING。syncWithMaster()函数主要是向Master发送sync命令,当该事件处理函数被触发以后会将Slave的状态改成REDIS_REPL_TRANSFER,表示Slave已经准备就绪要接收Master生成的rdb文件。
Master发现有一个Slave连接上来,如果此时的Master一个Slave都没有且没有后台快照进程,则启动一个后台进程将当前内存中的数据生成一个rdb文件,同时将Slave的状态置为REDIS_REPL_WAIT_BGSAVE_END状态,表示该Slave等待Master的快照进程结束。在后台进行生成rdb文件的时候,如果有对redis的更新命令,Master会将这些更新命令存到该Slave的buffer中,如果buffer满了会另外开辟list来存储这些更新命令。当后台快照进程结束,Master会将该Slave的状态改为REDIS_REPL_SEND_BULK,同时注册sendBulkToSlave()事件处理函数用于将生成的rdb文件传输给Slave。等rdb传输结束以后,sendBulkToSlave()事件函数会被删除,Slave的状态会被更改为REDIS_REPL_ONLINE,另外再注册sendReplyToClient()事件函数,将Master在快照内过程中的所有更新操作(Slave的buffer里存的命令)发给Slave。
当Master向Slave传输完rdb文件以后,Slave自身会将状态改为REDIS_REPL_CONNECTED,表示复制已完成,处于与Master保持实时同步的状态。
参考资料:
https://www.redis.cn/commands.html
https://blog.nosqlfan.com/html/3139.html
https://blog.csdn.net/gaogaoshan/article/details/41039581/
https://www.techweb.com.cn/news/2013-09-27/1339286.shtml
我们还真实同步,最近我也在研究redis