redis介绍
- Redis和Memcached类似,也属于k-v数据存储
- Redis官网redis.io, 当前最新稳定版4.0.1 支持更多value类型,除了和string外,还支持hash、lists(链表)、sets(集合)和sorted sets(有序集合)
- redis使用了两种文件格式:全量数据(RDB)和增量请求(aof)。
- rdb全量数据格式是把内存中的数据写入磁盘,便于下次读取文件进行加载。
- aof增量请求文件则是把内存中的数据序列化为操作请求,用于读取文件进行replay得到数据,这种类似于mysql binlog。
- redis的存储分为内存存储、磁盘存储和log文件三部分
redis安装
cd /usr/local/src/
下载
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
解压
tar -zxvf redis-4.0.1.tar.gz
cd redis-4.0.1
编译
make && make install
拷贝配置文件
cp redis.conf /etc/redis.conf
daemonize yes 后台启动(默认是no是前台启动)
vim /etc/redis.conf //修改如下配置
logfile "/var/log/redis.log" 定义日志文件路径
dir /data/redis_data/ 定义rdb和aof的存储目录
appendonly yes 开启aof日志
创建目录
mkdir /data/redis_data
启动redis
redis-server /etc/redis.conf
查看日志
less /var/log/redis.log 会出现一个内核警告。执行以下2条命令则不会告警
sysctl vm.overcommit_memory=1
echo never > /sys/kernel/mm/transparent_hugepage/enabled
停掉服务
killall redis-server
重启服务
redis-server /etc/redis.conf
默认监听6379端口
Redis持久化
- RDB:简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上,等于把内存的数据镜像一份在磁盘上,至于时间点是自己定义的:
在/etc/redis.conf里这里定义时间点
save 900 1 表示每15分钟且至少有1个key改变,就触发一次持久化
save 300 10 表示每5分钟且至少有10个key改变,就触发一次持久化
save 60 10000 表示每60秒至少有10000个key改变,就触发一次持久
save “” #这样可以禁用rdb持久化
- AOF:则是换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。(他这里也可以定义时间,always,everysec)
/etc/redis.cof
appendonly yes #如果是yes,则开启aof持久化
appendfilename “appendonly.aof” # 指定aof文件名字
appendfsync everysec #指定fsync()调用模式,
有三种
no(不调用fsync),
always(每次写都会调用fsync),
everysec(每秒钟调用一次fsync)。
第一种最快,第二种数据最安全,但性能会差一些,第三种为这种方案,默认为第三种。
关于rdb和aof那个恢复比较全面,一般为aof恢复比较全面,因为他是每秒写进数据文件里。
redis数据类型
-
string为最简单的类型,
-
与Memcached一样的类型,一个key对应一个value,其支持的操作与Memcached的操作类似,它的功能更丰富。设置可以存二进制的对象。
添加一个值(如果第二次赋值相同的Key会覆盖)
[root@study redis_data]# redis-cli
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> get name
"lisi"
127.0.0.1:6379>
获取这个值
127.0.0.1:6379> get name
"lisi"
查看一个key是否有值
127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> get key
"1"
127.0.0.1:6379> SETNX key 10 aa (利用setnx查看,返回0代表有值,没值返回1,也可以设置过期时间)
(integer) 0
127.0.0.1:6379>
多重创建值(利用mset创建,mget获取)
127.0.0.1:6379> MSET k1 1 k2 2 k3 3
OK
127.0.0.1:6379> MGET k1 k2 k3
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>
list数据类型
- list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。 使用 list 结构,我们可以轻松地实现最新消息排行等功能(比如新浪微博的 TimeLine )。list 的另一个应用就是消息队列,可以利用 list 的 push操作,将任务存在 list 中,然后工作线程再用pop操作将任务取出进行执行。
LPUSH存入
127.0.0.1:6379> LPUSH list 1
(integer) 1
127.0.0.1:6379> LPUSH list 2
(integer) 2
LRANGE查看
127.0.0.1:6379> LRANGE list 0 -1
1) "2"
2) "1"
LPOP取出
127.0.0.1:6379> LPOP list
"2"
127.0.0.1:6379> LPOP list
"1"
127.0.0.1:6379> LPOP list
(nil)
127.0.0.1:6379>
从最上面取值
lpop list
从最下面取值
rpop list
随机取出元素
SPOP set
从最上面插入值
lpush list XX
从最下面插入值
rpush list XX
指定index插入值(index就是开头的1234的标记数字)
linsert list before 2 3 //在2的前面插入一个元素为3
指定index修改值(注意,index是从0开始计算的,所有)
LSET list 1 aaa (所有实际修改的是2)
根据index查看元素
lindex list 0 (查看第一个元素)
查看链表有几个元素
llen list
set数据类型
- set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作。操作中key理解为集合的名字。比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。因为 Redis 非常人性化的为集合提供了求交集、并集、差集等操作,那么就可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中
sadd添加元素
127.0.0.1:6379> SADD set a
(integer) 1
127.0.0.1:6379> SADD set b
(integer) 1
127.0.0.1:6379> SADD set c
(integer) 1
smembers查看set元素
127.0.0.1:6379> SMEMBERS set
1) "a"
2) "b"
3) "c"
srem删除set元素
127.0.0.1:6379> SREM set c
(integer) 1
127.0.0.1:6379> SMEMBERS set
1) "a"
2) "b"
添加第二个元素
127.0.0.1:6379> sadd set1 a
(integer) 1
127.0.0.1:6379> sadd set1 d
(integer) 1
127.0.0.1:6379> SMEMBERS set1
1) "a"
2) "d"
sinter求交集(求相同的)
127.0.0.1:6379> SINTER set set1
1) "a"
sinterstore求交集并存储到set2里
sinterstore set set1 set2
sunion求并集(归纳在一起)
127.0.0.1:6379> SUNION set set1
1) "a"
2) "d"
3) "b"
sunionstore求并集并存储到set2里
sunionstore set set1 set2
sdiff求差集(求不同的元素),以前面的为标准
127.0.0.1:6379> SDIFF set set1
1) "b"
127.0.0.1:6379>
sdiffstore求差集后存储在set2里
sdiffstore set set1 set2
这种比较像数学,求相同,差异,交并
向集合seta中放入元素
127.0.0.1:6379> SADD set 1
(integer) 1
127.0.0.1:6379> SADD set 2
(integer) 1
127.0.0.1:6379> SADD set1 1
(integer) 1
127.0.0.1:6379> SADD set1 3
(integer) 1
127.0.0.1:6379> SADD set set1 加入set1
(integer) 1
127.0.0.1:6379> SRANDMEMBER set
"1"
127.0.0.1:6379> SMEMBERS set 查看
1) "set1"
2) "2"
3) "1"
127.0.0.1:6379>
sort set数据类型
- sorted set是有序集合,它比set多了一个权重参数score,使得集合中的元素能够按 score 进行有序排列,比如一个存储全班同学成绩的 Sorted Sets,其集合 value 可以是同学的学号,而 score 就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。
zadd添加元素
127.0.0.1:6379> ZADD test 99 lisi
(integer) 1
127.0.0.1:6379> ZADD test 80 xiaoming
(integer) 1
127.0.0.1:6379> ZADD test 70 xiaoqiang
(integer) 1
zrange查询可以看到是排序的由分数由低至高,那个分数就是定义权重
127.0.0.1:6379> ZRANGE test 0 -1
1) "xiaoqiang"
2) "xiaoming"
3) "lisi"
zrevrange倒序查看,100分的在第一
127.0.0.1:6379> ZREVRANGE test 0 -1
1) "lisi"
2) "xiaoming"
3) "xiaoqiang"
127.0.0.1:6379>
自带权重排序
hash类型
在 Memcached 中,我们经常将一些结构化的信息打包成 hashmap,在客户端序列化后存储为一个字符串的值(一般是 JSON 格式),比如用户的昵称、年龄、性别、积分等。
HSET 添加
127.0.0.1:6379> HSET hash name lisi
(integer) 1
127.0.0.1:6379> HSET hash age 30
(integer) 1
127.0.0.1:6379> hset hash joke banzuan
(integer) 1
hget获取
127.0.0.1:6379> HGET hash joke
"banzuan"
hgetall 获取全部元素
127.0.0.1:6379> HGETALL hash
1) "name"
2) "zhangqiang"
3) "age"
4) "29"
5) "joke"
6) "banzuan"
127.0.0.1:6379>
这种类型跟set有点像,都是可以设置一个组合,比如名字 李四,年龄 XX,不过set是带有权重排序的,而他没有。
批量建立
hmset user2 name aming age 30 job it //批量建立键值对
获取
hmget user2
hdel user2 job //删除指定filed
hkeys user2 //打印所有的key
hvals user2 //打印所有的values
hlen user2 //查看hash有几个filed
常用键值操作
keys * //取出所有key
keys my* //模糊匹配
exists name //有name键 返回1 ,否则返回0;
del key1 // 删除一个key //成功返回1 ,否则返回0;
EXPIRE key1 100 //设置key1 100s后过期
ttl key // 查看键 还有多长时间过期,单位是s,当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,返回 key 的剩余生存时间。
select 0 //代表选择当前数据库,默认进入0 数据库
move age 1 // 把age 移动到1 数据库(默认有16个库)
persist key1 //取消key1的过期时间
randomkey //随机返回一个key
rename oldname newname //重命名key
type key1 //返回键的类型
常用服务操作
dbsize //返回当前数据库中key的数目
info //返回redis数据库状态信息
flushdb //清空当前数据库中所有的键
flushall //清空所有数据库中的所有的key
bgsave //保存数据到 rdb文件中,在后台运行
save //作用同上,但是在前台运行
config get * //获取所有配置参数
config get dir //获取配置参数
config set dir //更改配置参数
数据恢复: 首先定义或者确定dir目录和dbfilename,然后把备份的rdb文件放到dir目录下面,重启redis服务即可恢复数据
redis安全设置
设置监听ip
bind 127.0.0.1 2.2.2.2//可以是多个ip,用空格分隔
设置监听端口
port 16000
设置密码
vim /etc/redis.conf
搜索requirepass添加下面这行
requirepass test
登录需要加-a指定密码
redis-cli -a 'aming>com'
将config命令改名
rename-command CONFIG aming
禁掉config命令
rename-command CONFIG “”
redis慢查询日志
vim /etc/redis.conf
搜索slowlog-log-slower-than
slowlog-log-slower-than 10000 表示慢于1毫秒则记录日志,单位为微妙换算后相当于1毫秒
slowlog-max-len 128 定义日志长度,表示最多存几条日志
我们改下记录时间单位,改为10微妙进行测试:
slowlog-log-slower-than 10
重启服务
killall redis-server
redis-server /etc/redis.conf
127.0.0.1:6379> SLOWLOG get 1
1) 1) (integer) 6
2) (integer) 1537349475
3) (integer) 17
4) 1) "SLOWLOG"
2) "get"
3) "1"
5) "127.0.0.1:52354"
6) ""
127.0.0.1:6379>
lowlog get //列出所有的慢查询日志
slowlog get 2 //只列出2条
slowlog len //查看慢查询日志条数
PHP使用redis安装扩展模块
cd /usr/local/src
wget https://coding.net/u/aminglinux/p/yuanke_centos7/git/raw/master/21NOSQL/phpredis.zip
unzip phpredis.zip
cd phpredis-develop
利用phpize生产configure文件
/usr/local/php-fpm/bin/phpize
./configure --with-php-config=/usr/local/php-fpm/bin/php-config
make && make install
vim /usr/local/php.ini//增加extension=redis.so
/usr/local/php-fpm/bin/php -m|grep redis//看是否有redis模块
重启php-fpm服务
PHP使用redis存储session
vim /usr/local/php-fpm/etc/php.ini//更改或增加
session.save_handler = "redis"
session.save_path = "tcp://127.0.0.1:6379"
下载测试文件
wget http://study.lishiming.net/.mem_se.txt
mv .mem_se.txt 1.php
然后重启PHP-fpm服务
curl localhost/1.php
1537350729<br><br>1537350729<br><br>unl72vvrt148ucj5sjr110g6jq 一般出现最后面的字符加数字ok
进入redis查看是否成功存储
127.0.0.1:6379> KEYS *
1) "PHPREDIS_SESSION:orikcehb3fl6ej7k1lg0b09ar2"
2) "key"
127.0.0.1:6379> get orikcehb3fl6ej7k1lg0b09ar2
(nil)
127.0.0.1:6379> get PHPREDIS_SESSION:orikcehb3fl6ej7k1lg0b09ar2
"TEST|i:1537350605;TEST3|i:1537350605;"
127.0.0.1:6379>
Redis主从配置
当数据量变得庞大的时候,读写分离还是很有必要的
cp /etc/redis.conf /etc/redis2.conf //拷贝配置文件
vim /etc/redis2.conf //需要修改port,dir,pidfile,logfile与主不一样
还要增加一行
slaveof 127.0.0.1 6379 //指定主
如果主上设置了密码,还需要增加
masterauth test //设置主的密码
启动之前不要忘记创建新的dir目录
mkdir /data/redis2_data
启动
redis-server /etc/redis2.conf
测试:在主上创建新的key,在从上查看
redis-cli -p 6378 //指定端口进入
注意:redis主从和mysql主从不一样,redis主从不用事先同步数据,它会自动同步过去,从上不能写入数据
redis集群:
Redis集群
基本介绍
Redis
集群是一个可以在多个Redis
节点之间进行数据共享的设施installation
。
Redis
集群不支持那些需要同时处理多个键的Redis
命令, 因为执行这些命令需要在多个Redis
节点之间移动数据, 并且在高负载的情况下, 这些命令将降低Redis
集群的性能, 并导致不可预测的行为。
Redis
集群通过分区partition
来提供一定程度的可用性availability
: 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis
集群提供了以下两个好处:
- 将数据自动切分
split
到多个节点的能力。- 当集群中的一部分节点失效或者无法进redis行通讯时, 仍然可以继续处理命令请求的能力。
redis原理图
所有的
redis
节点彼此互联(PING
-PONG
机制),内部使用二进制协议优化传输速度和带宽。节点的
fail
是通过集群中超过半数的节点检测失效时才生效。客户端与
redis
节点直连,不需要中间proxy
层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
redis-cluster
把所有的物理节点映射到[0-16383
]slot
上,cluster
负责维护node
<->slot
<->value
Redis
集群中内置了16384
个哈希槽,当需要在Redis
集群中放置一个key-value
时,redis
先对key
使用crc16
算法算出一个结果,然后把结果对16384
求余数,这样每个key
都会对应一个编号在0-16383
之间的哈希槽,redis
会根据节点数量大致均等的将哈希槽映射到不同的节点
redis集群配置
安装ruby2.2 (只需要一台机器上运行)
yum -y groupinstall "Development Tools"
yum -y install gdbm-devel libdb4-devel libffi-devel libyaml libyaml-devel ncurses-devel openssl-devel readline-devel tcl-deve
cd /root/
mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
wget http://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz -P rpmbuild/SOURCES
wget https://raw.githubusercontent.com/tjinjin/automate-ruby-rpm/master/ruby22x.spec -P rpmbuild/SPECS
rpmbuild -bb rpmbuild/SPECS/ruby22x.spec
yum -y localinstall rpmbuild/RPMS/x86_64/ruby-2.2.3-1.el7.centos.x86_64.rpm
gem install redis
配置操作:
cp /usr/local/src/redis-4.0.1/src/redis-trib.rb /usr/bin/
前3个IP默认为master,后面为从
redis-trib.rb create --replicas 1 192.168.133.130:7000 192.168.133.130:7002 192.168.133.130:7004 192.168.133.132:7001 192.168.133.132:7003 192.168.133.132:7005
redis-cli -c -h 192.168.133.130 -p 7000//-c说明以集群的方式登录
任意一个节点都可以创建key,或者查看key(演示)
redis-trib.rb check 192.168.133.130:7000//检测集群状态
cluster nodes//列出节点
cluster info//查看集群信息
cluster meet ip port //添加节点(直接添加都是为主)
cluster forget node_id //移除某个节点(移除必须是为从,先设置该机器为从,必须不在本机节点)
cluster replicate node_id//将当前节点设置为指定节点的从(需要登录该机器进行设置)
cluster saveconfig//保存配置文件