Jusene's Blog

redis浅析

字数统计: 3.7k阅读时长: 15 min
2017/06/25 Share

redis

redis(remote directory server)是一个key-value存储系统,和memcached类似,它支持存储的value类型相对较多,支持string,list,hash,set,sorted set,bitmaps,hyperloglogs,与memcached一样,为了保证效率,数据都是缓存在内存中,区别在于redis会周期性的把数据写入磁盘或把修改写入追加记录文件,并且在此基础上可以实现master-slave同步。

redis与memcached相比:

redis的优势:

  • 丰富的(资料形态)操作
    hash,list,set,sorted set,bitmaps,haperloglogs
  • 内建replication及cluster
  • 就地更新(in-place update)操作
  • 支持持久化(磁盘)
    避免雪崩效应

memcached的优势:

  • 多线程
    善用多核cpu
    更少的阻塞操作
  • 更少的内存开销
  • 更少的内存分配压力
  • 可能有更少的内存碎片

Nosql

我们都知道redis属于Nosql体系,而redis还属于redis中的KV Nosql体系,常见的Nosql体系:

  • KV NoSQL:redis memcached
  • Column Family NoSQL:HBase
  • Documentation NoSQL:MongoDB
  • Graph NoSQL:Neo4j

redis基本应用

  • redis-server:redis server主程序
  • redis-cli:redis client
  • redis-benchmark:redis 压力测试
  • redis-check-dump & redis-check-aof:redis rdb与aof检测工具

redis安装

redis官网:https://redis.io/download

1
~]# tar xf redis-3.2.9.tar.gz
2
~]# cd redis-3.2.9
3
~]# make 
4
~]# cd src
5
~]# make install
6
~]# cp ../redis.conf /etc/redis.conf

redis基本配置:

1
~]# vim /etc/redis.conf
2
bind 127.0.0.1
3
protected-mode yes
4
port 6379
5
tcp-backlog 511   
6
timeout 0
7
tcp-keepalive 300
8
daemonize yes
9
supervised no
10
pidfile "/var/run/redis_6379.pid"
11
loglevel notice
12
logfile "/var/log/redis/redis.log"
13
databases 16
14
~]# redis-server /etc/redis.conf

redis操作命令

key pattern查询相应的key

1
1)redis允许模糊查询key  有3个通配符  *、?、[]
2
2)randomkey:返回随机key  
3
3)type key:返回key存储的类型
4
4)exists key:判断某个key是否存在
5
5)del key:删除key
6
6)rename key newkey:改名
7
7)renamenx key newkey:如果newkey不存在则修改成功
8
8)move key 1:将key移动到1数据库
9
9)ttl key:查询key的生命周期(秒)
10
10)expire key 整数值:设置key的生命周期以秒为单位
11
11)pexpire key 整数值:设置key的生命周期以毫秒为单位
12
12)pttl key:查询key 的生命周期(毫秒)
13
13)perisist key:把指定key设置为永久有效

字符串类型的操作

1
1)set key value [ex 秒数] [px 毫秒数] [nx/xx]  
2
      如果ex和px同时写,则以后面的有效期为准
3
      nx:如果key不存在则建立
4
      xx:如果key存在则修改其值
5
2)get key:取值
6
3)mset key1 value1 key2 value2 一次设置多个值
7
4)mget key1 key2 :一次获取多个值
8
5)setrange key offset value:把字符串的offset偏移字节改成value
9
			如果偏移量 > 字符串长度,该字符自动补0x00
10
6)append key value :把value追加到key 的原值上
11
7)getrange key start stop:获取字符串中[start, stop]范围的值
12
			对于字符串的下标,左数从0开始,右数从-1开始
13
				注意:当start>length,则返回空字符串
14
					 当stop>=length,则截取至字符串尾
15
					 如果start所处位置在stop右边,则返回空字符串
16
8)getset key nrevalue:获取并返回旧值,在设置新值
17
9)incr key:自增,返回新值,如果incr一个不是int的value则返回错误,incr一个不存在的key,则设置key为1
18
10)incrby key 2:跳2自增
19
11)incrbyfloat by 0.7: 自增浮点数 
20
12)setbit key offset value:设置offset对应二进制上的值,返回该位上的旧值
21
				注意:如果offset过大,则会在中间填充0
22
					offset最大到多少
23
					2^32-1,即可推出最大的字符串为512M
24
13)bitop operation destkey key1 [key2..]    
25
				对key1 key2做opecation并将结果保存在destkey上
26
					opecation可以是AND OR NOT XOR
27
14)strlen key:取指定key的value值的长度
28
15)setex key time value:设置key对应的值value,并设置有效期为time秒

链表操作

redis的list类型其实就是每一个子元素都是string类型的双向链表,链表的最大的长度是2^32,list既可以做栈,也可以做队列。

1
1)lpush key value:把值插入到链表头部
2
2)rpush key value:把值插入到链表尾部
3
3)lpop key :返回并删除链表头部元素
4
4)rpop key: 返回并删除链表尾部元素
5
5)lrange key start stop:返回链表中[start, stop]中的元素
6
6)lrem key count value:从链表中删除value值,删除count的绝对值个value后结束
7
		count > 0 从表头删除  count < 0 从表尾删除  count=0 全部删除
8
7)ltrim key start stop:剪切key对应的链接,切[start, stop]一段并把改制重新赋给key
9
8)lindex key index:返回index索引上的值
10
9)llen key:计算链表的元素个数
11
10)linsert key after|before search value:在key 链表中寻找search,并在search值之前|之后插入value
12
11)rpoplpush source dest:把source 的末尾拿出,放到dest头部,并返回单元值
13
12)brpop,blpop key timeout:等待弹出key的尾/头元素
14
		timeout为等待超时时间,如果timeout为0则一直等待下去

hashes类型操作

hash是string类型的field和value的映射表,hash特别适合于存储对象,将一个对象存储在hash类型会占用更少的内存,并且方便的存取整个对象。
配置:
hash_max_zipmap_entries 64 #配置字段最多64个
hash_max_zipmap_value 512 #配置value最大为512字节

1
1)hset myhash field value:设置myhash的field为value
2
2)hsetnx myhash field value:不存在的情况下设置myhash的field为value
3
3)hmset myhash field1 value1 field2 value2:同时设置多个field
4
4)hget myhash field:获取指定的hash field
5
5)hmget myhash field1 field2:一次获取多个field
6
6)hincrby myhash field 5:指定的hash field加上给定的值
7
7)hexists myhash field:测试指定的field是否存在
8
8)hlen myhash:返回hash的field数量
9
9)hdel myhash field:删除指定的field
10
10)hkeys myhash:返回hash所有的field
11
11)hvals myhash:返回hash所有的value
12
12)hgetall myhash:获取某个hash中全部的field及value

集合结构操作

特点:无序性、确定性、唯一性

1
1)sadd key value1 value2:往集合里面添加元素
2
2)smembers key:获取集合所有的元素
3
3)srem key value:删除集合某个元素
4
4)spop key:返回并删除集合中1个随机元素(可以坐抽奖,不会重复抽到某人)   
5
5)srandmember key:随机取一个元素
6
6)sismember key value:判断集合是否有某个值
7
7)scard key:返回集合元素的个数
8
8)smove source dest value:把source的value移动到dest集合中
9
9)sinter key1 key2 key3:求key1 key2 key3的交集
10
10)sunion key1 key2:求key1 key2 的并集
11
11)sdiff key1 key2:求key1 key2的差集
12
12)sinterstore res key1 key2:求key1 key2的交集并存在res里

有序集合操作

1
1)zadd key score1 value1:添加元素
2
2)zrange key start stop [withscore]:把集合排序后,返回名次[start,stop]的元素  默认是升续排列  withscores 是把score也打印出来
3
3)zrank key member:查询member的排名(升序0名开始)
4
4)zrangebyscore key min max [withscores] limit offset N:集合(升序)排序后取score在[min, max]内的元素,并跳过offset个,取出N个
5
5)zrevrank key member:查询member排名(降序 0名开始)
6
6)zremrangebyscore key min max:按照score来删除元素,删除score在[min, max]之间
7
7)zrem key value1 value2:删除集合中的元素
8
8)zremrangebyrank key start end:按排名删除元素,删除名次在[start, end]之间的
9
9)zcard key:返回集合元素的个数
10
10)zcount key min max:返回[min, max]区间内元素数量
11
11)zinterstore dest numkeys key1[key2..] [WEIGHTS weight1 [weight2...]] [AGGREGATE SUM|MIN|MAX]
12
		求key1,key2的交集,key1,key2的权值分别是weight1,weight2
13
		聚合方法用 sum|min|max
14
		聚合结果 保存子dest集合内
15
		注意:weights,aggregate如何理解?
16
17
			答:如果有交集,交集元素又有score,score怎么处理?aggregate num->score相加,min最小score,max最大score,另外可以通过weights设置不同的key的权重,交集时  score*weight

服务器相关命令

1
1)ping:测定连接是否存活
2
2)echo:在命令行打印一些内容
3
3)select:选择数据库
4
4)quit:退出连接
5
5)dbsize:返回当前数据库中key的数目
6
6)info:获取服务器的信息和统计
7
7)monitor:实时转储收到的请求
8
8)config get 配置项:获取服务器配置的信息
9
		config set 配置项  值:设置配置项信息
10
9)flushdb:删除当前选择数据库中所有的key
11
10)flushall:删除所有数据库中的所有的key
12
11)time:显示服务器时间,时间戳(秒),微秒数
13
12)bgrewriteaof:后台重写aof文件
14
13)bgsave:后台保存rdb快照
15
14)save:保存rdb快照
16
15)lastsave:上次保存时间
17
16)shutdown [save/nosave]
18
	注意:如果不小心运行了flushall,立即shutdown nosave,关闭服务器,然后手工编辑aof文件,去掉文件中的flushall相关行,然后开启服务器,就可以倒回原来是数据。如果flushall之后,系统恰好bgwriteaof了,那么aof就清空了,数据丢失。
19
17)showlog:显示慢查询
20
		问:多慢才叫慢?
21
		答:由slowlog-log-slower-than 10000,来指定(单位为微秒)
22
		问:服务器存储多少条慢查询记录
23
	   答:由slowlog-max-len 128,来做限制

redis认证

1
~]# vim /etc/redis.conf
2
requirepass jusene
3
4
~]# redis-cli
5
127.0.0.1:6379>auth jusene

redis事务

通过multi,exec,watch等命令实现事务功能: 将一个或多个命令归并为一个操作提请服务器按顺序执行的机制,不支持回滚操作

  • multi:启动一个事务
  • exec:执行事务
    一次性将事务中的所有操作执行完成后返回给客户端
  • watch:乐观锁:在exec命令行之前,用于监视指定数量键:如果监视中的某任意键数据被修改,则服务器拒绝执行事务
    1
    127.0.0.1:6379> multi
    2
    OK
    3
    127.0.0.1:6379> set ip 192.168.1.2
    4
    QUEUED
    5
    127.0.0.1:6379> set port 3306
    6
    QUEUED
    7
    127.0.0.1:6379> exec
    8
    1) OK
    9
    2) OK

watch

1
127.0.0.1:6379> watch ip
2
OK
3
127.0.0.1:6379> multi
4
OK
5
127.0.0.1:6379> set ip 1.1.1.1     在事务执行的过程中,ip键发生改变则此处事务拒绝执行
6
QUEUED
7
127.0.0.1:6379> exec
8
(nil)

发布和订阅

  • 1) PSUBSCRIBE pattern [pattern …] 通配订阅频道
  • 2) PUBLISH channel message 发布信息
  • 3) PUNSUBSCRIBE [pattern [pattern …]] 通配取消订阅频道
  • 4) SUBSCRIBE channel [channel …] 订阅频道
  • 5) UNSUBSCRIBE [channel [channel …]] 取消订阅频道

订阅new频道

1
127.0.0.1:6379> SUBSCRIBE new
2
Reading messages... (press Ctrl-C to quit)
3
1) "subscribe"
4
2) "new"
5
3) (integer) 1

发布信息

1
127.0.0.1:6379> PUBLISH new hello
2
(integer) 1

频道接受到信息

1
127.0.0.1:6379> SUBSCRIBE new
2
Reading messages... (press Ctrl-C to quit)
3
1) "subscribe"
4
2) "new"
5
3) (integer) 1
6
1) "message"
7
2) "new"
8
3) "hello"

统配订阅频道

1
127.0.0.1:6379> PSUBSCRIBE new*
2
Reading messages... (press Ctrl-C to quit)
3
1) "psubscribe"
4
2) "new*"
5
3) (integer) 1
6
1) "pmessage"
7
2) "new*"
8
3) "new"
9
4) "hello"
10
1) "pmessage"
11
2) "new*"
12
3) "news"
13
4) "hello"

redis持久化

redis持久化有两种方式:
RDB和AOF

  • RDB:snapshot,二进制格式,按事先定制的策略,周期性将数据保存磁盘,数据文件默认为dump.rdb
    客户端也可以使用save或bgsave命令启动快照保存机制
    save:同步,在主线程中保存快照,此时会阻塞所有客户端请求
    bgsave:异步,不会造成阻塞
    相当于mysql周期性备份

  • AOF:Append Only File
    通过记录每一次写操作至指定的文件尾部实现持久化:当redis重启时,可通过重新执行文件中的命令在内存重建数据库;
    bgrewriteaof:aof文件重写
    不会读取正在使用的aof文件,而是通过将内存中的数据以命令的方式保存到临时文件中,完成之后替换原来的aof文件
    相当于mysql的binlog

RDB:

1
SAVE 900 1
2
SAVE 300 10
3
SAVE 60 10000
4
stop-writes-on-bgsave-error yes
5
rdbcompression yes
6
rdbchecksum yes
7
dbfilename dump.rdb
8
dir ./

AOF:
重写过程:

  • (1)redis主进程通过fork创建子进程
  • (2)子进程根据redis内存中的数据创建数据库重建命令序列于临时文件中
  • (3)父进程继承client的请求,并把这些请求的写操作继续追加至原来的aof文件中:额外地,这些新的写请求还会被放置于一个缓冲队列中
  • (4)子进程重写完成,会通知父进程:父进程把缓冲队列的命令写到临时文件中
  • (5)父进程用临时文件替换老的aof文件

相关参数:

1
appendonly no
2
appendfilename "appendonly.aof"
3
# appendfsync always
4
appendfsync everysec
5
# appendfsync no
6
no-appendfsync-on-rewrite no
7
auto-aof-rewrite-percentage 100
8
auto-aof-rewrite-min-size 64mb

注意:持久本身不能取代备份,还应该制定备份策略,对redis数据库定期进行备份

rdb与aof同时启用:

  • (1)bgsave和bgrewriteaof不会同时执行
  • (2)在redis服务器启动用于恢复数据时,会优先使用aof

redis主从复制

特点:

  • 一个master可以有多个slave
  • 支持链式复制
  • master以非阻塞方式同步数据至slave

从服务器:

1
slaveof masterip masterport

redis.conf

1
slaveof masterip masterport
2
masterauth <master-password>
3
slave-serve-stale-data yes   当与主服务器断开时,数据是否可用
4
slave-read-only yes
5
repl-diskless-sync no        当在低io高带宽的场景,使用diskless的方法同步磁盘数据
6
repl-diskless-sync-delay 5
7
slave-priority 100            多个slave时的优先级

redis sentinel集群

redis sentinel(哨兵)可以有效的容灾,当主服务器宕机时,可以选出从服务器中的一台来作为主服务器来使用。

sentinel的作用:

  1. 监控:监控主从是否正常
  2. 通知:出现问题时,可以通知相关人员
  3. 故障迁移:自动主从切换
  4. 统一的配置管理:连接者询问sentinel取得主从的地址
1
~]# cp sentinel.conf /etc/sentinel.conf
2
~]# cat sentinel.conf
3
port 26371
4
daemonize yes
5
dir "/tmp"
6
logfile "/var/log/redis/sentinel.log"
7
sentinel myid 8cd979a05f7bbfb2dbd38d935c56ee0a0c193dd0
8
#sentinel auth-pass <master-name> <password>
9
sentinel down-after-milliseconds <master-name> <milliseconds> #master和slave多长时间(默认30秒)不能使用后标记为sdown状态
10
sentinel monitor <master-name> <ip> <redis-port> <quorum>  #哨兵监控这个master,在至少quorum个哨兵实例都认为master down后把master标记为odown(objective down客观down;相对应的存在sdown,subjective down,主观down)
11
sentinel failover-timeout <master-name> <milliseconds>  #若sentinel在该配置值内未能完成failover操作(即master/slave自动切换),则认为本次failover失败
12
sentinel parallel-syncs <master-name> <numslaves>  #当切换主从状态后,设定一个最低值值数量slaves来同步
13
14
sentinel config-epoch TestMaster 15
15
sentinel leader-epoch TestMaster 8394
16
17
#除了当前哨兵, 还有哪些在监控这个master的哨兵
18
sentinel known-sentinel <master-name> 127.0.0.1 26372 0aca3a57038e2907c8a07be2b3c0d15171e44da5
19
sentinel known-sentinel <master-name> 127.0.0.1 26373 ac1ef015411583d4b9f3d81cee830060b2f29862
20
21
sentinel current-epoch 8394

sentiel 启动:

1
~]# redis-sentinel /etc/sentinel.conf
2
~]# redis-server /etc/sentinel.conf --sentinel

专有命令:

1
sentinel masters
2
sentinel slaves <master name>
3
sentinel get-master-addr-by-name <master name>
4
sentinel reset
5
sentinel failover <master name>
CATALOG
  1. 1. redis
  2. 2. Nosql
  3. 3. redis基本应用
    1. 3.1. redis安装
    2. 3.2. redis操作命令
      1. 3.2.1. key pattern查询相应的key
      2. 3.2.2. 字符串类型的操作
      3. 3.2.3. 链表操作
      4. 3.2.4. hashes类型操作
      5. 3.2.5. 集合结构操作
      6. 3.2.6. 有序集合操作
      7. 3.2.7. 服务器相关命令
  4. 4. redis认证
  5. 5. redis事务
  6. 6. 发布和订阅
  7. 7. redis持久化
  8. 8. redis主从复制
  9. 9. redis sentinel集群