一,Redis 支持的数据类型及使用方法
Redis最为常用的数据类型主要有以下五种:
1, string(字符串类型):String是最常用的一种数据类型,普通的key/value存储都可以归为此类;
常用命令:set,get,decr,incr,mget,mset,append,strlen 等。
127.0.0.1:6379> help @string #查看string可以支持的所有操作 ...... 127.0.0.1:6379> set counter 1 #计数自增,在memcache中不可用 OK 127.0.0.1:6379> incr counter (integer) 2 127.0.0.1:6379> incr counter (integer) 3 127.0.0.1:6379> incrby counter 2 #指定自增步长 (integer) 5 127.0.0.1:6379> incrby counter 3 (integer) 8 127.0.0.1:6379> decr counter #自减 (integer) 7 127.0.0.1:6379> decrby counter 2 #已指定的步长自减 (integer) 5 127.0.0.1:6379> set name feiyu OK 127.0.0.1:6379> getset name feiyu-now #getset 获取上一个值并将其设置为当前值 "feiyu" 127.0.0.1:6379> get name "feiyu-now" 127.0.0.1:6379> mset name feiyu age 20 sex male #批量设置与读取 OK 127.0.0.1:6379> mget name age sex 1) "feiyu" 2) "20" 3) "male" 127.0.0.1:6379> append name student #为一个值添加内容 (integer) 12 127.0.0.1:6379> get name "feiyustudent" 127.0.0.1:6379> strlen name #求长度 (integer) 12 127.0.0.1:6379> substr name 0 6 #取字串 "feiyust" 127.0.0.1:6379> substr name 2 4 "iyu"
2,list(列表类型 ):redis 的 list 类型其实就是一个每个子元素都是 string 类型的双向链表,这就意味着即使你有成千上万中元素在list中,添加一个新元素到list开头或者结尾的操作算法时间复杂度都是O(1)。
常用命令:lpush,rpush,lpop,rpop,lrange 等。
127.0.0.1:6379> help @list 127.0.0.1:6379> lpush students feiyu1 feiyu2 feiyu3 (integer) 3 127.0.0.1:6379> llen students #求一个列表的长度 (integer) 3 127.0.0.1:6379> lrange students 0 3 #输出列表的范围 1) "feiyu3" 2) "feiyu2" 3) "feiyu1" 127.0.0.1:6379> lpop students #移除第一个元素 "feiyu3" 127.0.0.1:6379> lrem students 2 feiyu1 #移除指定元素 (integer) 1 127.0.0.1:6379> linsert students before feiyu-4 feiyu-3 #插入元素 (integer) 4 127.0.0.1:6379> lrange students 0 6 1) "feiyu-5" 2) "feiyu-3" 3) "feiyu-4" 4) "feiyu2" 127.0.0.1:6379> rpush students feiyu4 (integer) 1 说明:lpush 是将元素添加到列表的第一个,而 rpush 是将元素添加到列表的最后一个,lpop 和 rpop 同理。
3,set (集合): redis的set是string类型的无序集合。set元素最大可以包含(2的32次方-1)个元素。set的是通过hash table实现的,所以添加,删除,查找的复杂度都是O(1)。hash table会随着添加或者删除自动的调整大小。
常用命令:sadd,spop,smembers,sunion 等。
127.0.0.1:6379> help @set ...... 127.0.0.1:6379> sadd users feiyu1 feiyu2 feiyu3 (integer) 3 127.0.0.1:6379> SMEMBERS users 1) "feiyu2" 2) "feiyu1" 3) "feiyu3" 127.0.0.1:6379> SISMEMBER users feiyu1 #检查元素是否存在 (integer) 1 127.0.0.1:6379> SISMEMBER users feiyu4 (integer) 0 redis 127.0.0.1:6379> spop users
4,hash(哈希类型):redis hash是一个string类型的field和value的映射表.它的添加,删除操作都是O(1)(平均),hash特别适合用于存储对象。相较于将对象的每个字段存成单个string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。
常用命令: hset,hget,hmget,hmset,hlen,hvals,hgetall 等
127.0.0.1:6379> help @hash 127.0.0.1:6379> hset test name feiyu (integer) 1 127.0.0.1:6379> hset test age 20 (integer) 1 127.0.0.1:6379> hset test sex male (integer) 1 127.0.0.1:6379> hvals test #Get all the values in a hash 1) "feiyu" 2) "20" 3) "male" 127.0.0.1:6379> hgetall test 1) "name" 2) "feiyu" 3) "age" 4) "20" 5) "sex" 6) "male"
5,sorted set:和set一样sorted set也是string类型元素的集合,不同的是每个元素都会关联一个double类型的score。
常用命令:zadd,zcount,zrange 等
redis 127.0.0.1:6379> help @sorted_set ...... 127.0.0.1:6379> zadd days 0 sun (integer) 1 127.0.0.1:6379> zadd days 2 tue (integer) 1 127.0.0.1:6379> zadd days 1 mon (integer) 1 127.0.0.1:6379> ZRANGE days 0 6 #自动排序 1) "sun" 2) "mon" 3) "tue"
数据类型使用建议:
key建议:
-object-type:id:field
-长度 10 到 20
value 建议:
-string 不要超过 2K
-set sortedset元素不要超过 5000
– 根据不同长度规划不同的实例端口
二,Redis的持久化机制
Redis一共支持四种持久化方式,分别是:
定时快照方式(snapshot)
基于语句追加文件的方式(aof)
虚拟内存(vm)
Diskstore方式
目前,实际能在生产环境用的只有前两种,快照方式是 redis 默认的,前两种是基于全部数据都在内存中,只能作为小数据量存储,后两种方式还在实验阶段。
定时快照方式(snapshot):
该持久化方式实际是在Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件,如果满足则通过操作系统fork调用来创建出一个子进程,这个子进程默认会与父进程共享相同的地址空间,这时就可以通过子进程来遍历整个内存来进行存储操作,而主进程则仍然可以提供服务,当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。
该持久化的主要缺点是定时快照只是代表一段时间内的内存映像,所以系统重启会丢失上次快照与重启之间所有的数据。
基于语句追加方式(aof):
aof 方式实际类似MySQL的基于语句的 binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。
aof的方式的主要缺点是追加log文件可能导致体积过大,当系统重启恢复数据时如果是aof的方式则加载数据会非常慢,几十G的数据可能需要几小时才能加载完,当然这个耗时并不是因为磁盘文件读取速度慢,而是由于读取的所有命令都要在内存中执行一遍。另外由于每条命令都要写log,所以使用aof的方式,Redis的读写性能也会有所下降。
启用 aof 后,如果测试时使用 del 删除变量,则也会记录到日志中。
配置方式请参考上文 Redis 安装与配置详解。
三,配置 redis 多实例
redis 多实例的配置方式和 mysql 的配置方式相似,都可以创建不同的数据的目录,再使用不同的端口,下面使用6380 端口配置另一个实例。
配置方法: 修改数据文件目录,端口号,pid 文件
[root@localhost redis]# mkdir /data/6380/redis_data -p [root@localhost redis]# cp redis.conf /data/6380/redis_data/ [root@localhost redis]# cd !$ cd /data/6380/redis_data/ 修改配置文件: 46 pidfile /data/6380/redis_data/redis.pid 50 port 6380 197 dir /data/6380/redis_data/ #数据保存目录 [root@localhost redis_data]# redis-server /data/6380/redis_data/redis.conf & #启动 [root@localhost redis_data]# ss -tln | egrep '6379|6380' #查看端口信息 LISTEN 0 128 *:6379 *:* LISTEN 0 128 :::6379 :::* LISTEN 0 128 *:6380 *:* LISTEN 0 128 :::6380 :::* [root@localhost redis_data]# redis-cli -p 6380 -a feiyu 127.0.0.1:6380> set name feiyu OK 127.0.0.1:6380> get name "feiyu" 127.0.0.1:6380> save 35320:M 30 Apr 02:35:39.912 * DB saved on disk OK [root@localhost redis_data]# cat appendonly.aof #查看持久化日志,前提是启用了aof *2 $6 SELECT $1 0 *3 $3 set $4 name $5 feiyu
ok,实际上配置就是如此简单!
四,配置 redis 主从同步
为了配置简单,依然使用上面的另一个实例进行同步:
[root@localhost redis_data]# vim redis.conf #修改从服务器的配置文件 只需要在从库上配置两个参数(没有密码只写一个ip就行了): 217 slaveof 192.168.1.224 6379 224 masterauth feiyu
然后重新启动 master 和 slave
master启动日志:
slave 启动日志:
从库对主库每隔10s 有个 ping 操作
slave: 127.0.0.1:6380> monitor OK 1462015400.318109 [0 192.168.1.224:6379] "PING" 1462015410.422364 [0 192.168.1.224:6379] "PING" 127.0.0.1:6380> set name feiyu #slave 不能写数据 (error) READONLY You can't write against a read only slave. 127.0.0.1:6380> info replication #查看主从状态信息 # Replication role:slave master_host:192.168.1.224 master_port:6379 master_link_status:up master_last_io_seconds_ago:10 master_sync_in_progress:0 slave_repl_offset:1403 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
五,redis 高级特性:发布订阅
使用 redis 发布订阅的功能可以在某些场合避免自己使用网络编程重写某些功能。
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
127.0.0.1:6379> publish channel-01 hello1 #在服务器端发布 (integer) 0 127.0.0.1:6379> publish channel-02 hello2 (integer) 0 127.0.0.1:6380> subscribe channel-01 #收听一个频道 127.0.0.1:6380> psubscribe channel* #收听多个频道 Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "channel*" 3) (integer) 1 1) "pmessage" 2) "channel*" 3) "channel-01" ---> 频道 4) "hello1" --------> 收到的消息 1) "pmessage" 2) "channel*" 3) "channel-02" -----> 频道 4) "hello2"
六,redis优化
1,根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数。
2,当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量。
3,如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。
4,不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。
5,redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。redis.conf文件中 vm-enabled 为 no
6,大数据量尽量按业务使用多个redis 实例吧数据分散开。
此外,变量的命名方式尽量短点。
七,其他功能
类似于 mysql 一样热修改配置文件参数:
redis 127.0.0.1:6379> config set appendonly yes #相当与 set global variables=?; OK redis 127.0.0.1:6379> config get appendonly 1) "appendonly" 2) "yes" redis 127.0.0.1:6379> config get * #查看所有的配置,相当与mysql的show variables; ...... redis 127.0.0.1:6379> config resetstat #清零所有的状态 OK