redis
redis安装与配置
-
获取redis资源
wget http://download.redis.io/redis-stable.tar.gz
-
解压
tar -xzvf redis-stable.tar.gz
-
安装
cd redis-stable make cd src make install PREFIX=/usr/local/redis
make报错:
MAKE hiredis cd hiredis && make static make[3]: Entering directory `/root/redis-stable/deps/hiredis' cc -std=c99 -pedantic -c -O3 -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb net.c make[3]: cc: Command not found make[3]: *** [net.o] Error 127 make[3]: Leaving directory `/root/redis-stable/deps/hiredis' make[2]: *** [hiredis] Error 2 make[2]: Leaving directory `/root/redis-stable/deps' make[1]: [persist-settings] Error 2 (ignored) CC adlist.o /bin/sh: cc: command not found make[1]: *** [adlist.o] Error 127 make[1]: Leaving directory `/root/redis-stable/src' make: *** [all] Error 2
解决办法:安装gcc
yum install -y gcc
make报错:
zmalloc.h:50:31: error: jemalloc/jemalloc.h: No such file or directory
zmalloc.h:55:2: error: #error "Newer version of jemalloc required"
make[1]: *** [adlist.o] Error 1
make[1]: Leaving directory `/data0/src/redis-2.6.2/src'
make: *** [all] Error 2
原因是jemalloc重载了Linux下的ANSI C的malloc和free函数。解决办法:make时添加参数。
make MALLOC=libc
报错:
serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
^
server.c:5103:19: error: ‘struct redisServer’ has no member named ‘supervised_mode’
if (server.supervised_mode == SUPERVISED_SYSTEMD) {
^
server.c:5104:24: error: ‘struct redisServer’ has no member named ‘masterhost’
if (!server.masterhost) {
^
server.c:5117:15: error: ‘struct redisServer’ has no member named ‘maxmemory’
if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {
^
server.c:5117:39: error: ‘struct redisServer’ has no member named ‘maxmemory’
if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {
^
server.c:5118:176: error: ‘struct redisServer’ has no member named ‘maxmemory’
serverLog(LL_WARNING,"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory);
^
server.c: In function ‘hasActiveChildProcess’:
server.c:1476:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘allPersistenceDisabled’:
server.c:1482:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘writeCommandsDeniedByDiskError’:
server.c:3747:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘iAmMaster’:
server.c:4914:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
make[1]: *** [server.o] Error 1
make[1]: Leaving directory `/usr/src/redis-6.0.1/src'
make: *** [install] Error 2
解决办法:
# 查看gcc版本是否在5.3以上,centos7.6默认安装4.8.5
gcc -v
# 升级gcc到5.3及以上,如下:
升级到gcc 9.3:
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。
如果要长期使用gcc 9.3的话:
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
这样退出shell重新打开就是新版的gcc了
以下其他版本同理,修改devtoolset版本号即可。
安装好后进行
make test
报错 :You need tcl 8.5 or newer in order to run the Redis test
解决办法:安装tcl
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make
sudo make install
-
移动配置文件到安装目录下
cd ../ mkdir /usr/local/redis/etc cp redis.conf /usr/local/redis/etc
-
配日志redis为后台启动,并修改存储路径
vi /usr/local/redis/etc/redis.conf #将daemonize no 改为 daemonize yes #数据文件 dbfilename dump.rdb #数据文件存储路径 默认为dir ./ 提前创建/var/lib/redis文件夹 dir /var/lib/redis #日志文件 提前创建/var/log/redis/目录 logfile "/var/log/redis/redis-server.log" #数据库,默认有16个 database 16 #主从复制,类似于双机备份 slaveof
-
将redis加入到开机启动
vi /etc/rc.local //在里面添加内容:/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf (意思就是开机调用这段开启redis的命令)
-
将redis加入centos的systemctl服务
cd /usr/lib/systemd/system vim redis.service [Unit] Description=Redis Server After=network.target [Service] # pid文件和redis配置设置的pid一致 PIDFile=/var/run/redis_6379.pid # redis-server路径和配置文件 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf # redis-cli # ExecStop=/usr/local/redis/bin/redis-cli -a password shutdown ExecStop=/bin/kill -s QUIT $MAINPID ExecReload=/bin/kill -s HUP $MAINPID [Install] WantedBy=mutli-user.target systemctl enable redis.service //加入开机启动,先执行这个 systemctl start redis //开启redis服务 systemctl status redis //查看redis运行状态
-
添加环境变量
vim ~/.bashrc export PATH=$PATH:/usr/local/redis/bin source ~/.bashrc
-
开启redis服务端
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
-
常用命令
redis-server /usr/local/redis/etc/redis.conf //启动redis
pkill redis //停止redis
# 卸载redis:
rm -rf /usr/local/redis //删除安装目录
rm -rf /usr/bin/redis-* //删除所有redis相关命令脚本
m -rf /root/download/redis-4.0.4 //删除redis解压文件夹
-
开启redis客户端
#连接rediscil +端口号 默认127.0.0.1 redis-cli #切换数据库 #数据库有名称,默认有16个,通过0-15来标识,连接redis默认选择第一个数据库 select n
redis 数据操作
redis是key-value的数据结构,每条数据都是一个键值对
键的类型是字符串,键不能重复。
值得类型分为五种:String、hash、list、set(集合)、zset(有序集合)
-
String
redis重字符串类型的value最多可以容纳得数据长度是512M。
如果设置的键不存在则为添加,如果设置的键已经存在则为修改。
set key value
设置键值及过期时间,以秒为单位
setex key seconds value
设置多个键值
mset key1 value1 key2 value2 ...
追加值
append key value
根据键获取值,如果不存在此键则返回nil
get key
根据多个键获取多个值
megt key1 key2 key3
-
键命令
查找键,参数支持正则表达式
keys pattern # keys * 查找所有键 # keys a* 查看名称中包含a的键
判断键是否存在,如果存在返回1,不存在返回0
exists key
查看键的类型
type key
删除键及对应的值
del key1 key2 ...
设置过期时间,以秒为单位
如果没有指定过期时间则一直存在,知道使用DEL移除
expire key seconds
查看有效时间,以秒为单位
ttl key
-
hash
hash用于存储对象,对象的结构为属性、值,值的类型为string
设置单个属性
hset key field value # hset user name haha 设置user键的值为 name属性对应值为haha
如果redis被配置为保存数据库快照,但它不能持久化到硬盘。用来修改集合数据的命令不能用
运行
config set stop-writes-on-bgsave-error no
命令狗,关闭快照。设置多个属性
hmset key field1 value1 field2 value2 field3 value3...
获取键值
hget key field
获取多个属性的值
hegt key field1 field2
获取所有属性的值
hvals key
删除整个hash键及值,使用del命令
删除属性,属性对应的值会被一起删除
hdel key field1 field2...
-
list
列表的元素类型为string,按照插入顺序排序
在左侧插入数据
lpush key value1 value2 ...
在右侧插入数据
rpush key value1 value2 ...
在指定元素的前面和后面插入数据
linsert key before/after new old # 在键为 a1 的列表中元素 b 前插入 3 # linsert a1 before b 3
返回列表里指定范围内的元素
start、stop为元素的下标索引
索引从左侧开始,第一个元素为0
索引可以是负数,表示从尾部开始计数,如-1表示最后一个元素
lrange key start stop
# 查看a1的所有元素
# lrange a1 0 -1
设置指定索引位置的元素值
索引从左侧开始,第一个元素为9
所以可以是负数,表示尾部开始计数,如-1表示最后一个元素
lset key index value
删除指定元素
将列表中前count次出现的值为value的元素移除
count > 0: 从头向尾移除
count < 0: 从尾向头移除
count = 0: 移除所有
lrem key count value
-
set
无序集合、元素为string类型,元素具有唯一性,不重复、对于集合没有修改操作
添加元素
sadd key member1 member2 # sadd a3 zhangsan lisi wangwu
返回所有的元素
smembers key
删除指定的元素
srem key value
-
zset
有序集合、元素为string类型,元素具有唯一性,不重复、对于集合没有修改操作
每个元素都会关联一个double类型的score,表示权重,通过权重将元素从小到大排序
添加元素
zadd key score1 member1 score2 member2 ... # 向键a4的集合重添加元素 zhangsan lisi wangwu, 权重分别为3 4 5 # zadd a4 3 zhangsan 4 lisi 5 wangwu
返回指定范围内的元素
start、stop为元素的下标索引
索引从左侧开始,第一个元素为0
索引可以是负数,表示从尾部开始计数,如-1表示最后一个元素
zrange key start stop
返回score值在min和max之间的成员
zrangebyscore key min max
# min 和 max 包括在内
返回成员member的score值
zscore key member
删除指定元素
zrem key member1 member2 ...
删除权重在指定范围的元素
zremrangebyscore key min max
# min 和 max 包括在内
搭建主从
一个master可以拥有多个slave,一个slave又可以拥有多个slave,如此下去,形成强大的多级服务器集群架构
master用来写数据,slave用来读数据,经统计:网站的读写比率是10:1
通过主从配置可以实现读写分离
主从可以是不同的服务器,也可以在同一台服务器,在同一台服务器时,端口号要设置不一样
-
在主服务节点上,修改etc/redis/redis.conf文件
vi redis.conf bind 192.168.220.132
-
重启redis服务
systemctl restart redis # 同一台服务器上需要启动不同的配置文件 systemctl stop redis redis-server /usr/local/redis/etc/redis.conf
-
在从服务节点上,修改etc/redis/slave.conf文件(内容可以从主服务复制)
vi slave.conf bind 192.168.220.133 slaveof 192.168.220.132 6379 port 6379 # 同一台服务器上需要绑定不同的端口
-
启动redis服务
redis-server /usr/local/redis/etc/slave.conf
-
查看主从关系
redis-cli -h 192.168.220.132 -p 6379 info Replication
搭建集群
192.168.220.132
192.168.220.133
- 配置服务器1 (192.168.220.132)
在/usr/local/redis/etc/conf/目录下创建三个文件分别为7000.conf、7001.conf、7002.conf
port 7000
bind 192.168.220.132
daemonize yes
pidfile 7000.pid
cluster-enabled yes
cluster-config-file 7000_node.conf
cluster-node-timeout 15000
appendonly yes
port 7001
bind 192.168.220.132
daemonize yes
pidfile 7001.pid
cluster-enabled yes
cluster-config-file 7001_node.conf
cluster-node-timeout 15000
appendonly yes
port 7002
bind 192.168.220.132
daemonize yes
pidfile 7002.pid
cluster-enabled yes
cluster-config-file 7002_node.conf
cluster-node-timeout 15000
appendonly yes
使用配置文件启动redis服务
redis-server /usr/local/redis/etc/conf/7000.conf
redis-server /usr/local/redis/etc/conf/7001.conf
redis-server /usr/local/redis/etc/conf/7002.conf
- 配置服务器2(192.168.220.133)
在/usr/local/redis/etc/conf/目录下创建三个文件分别为7003.conf、7004.conf、7005.conf
port 7003
bind 192.168.220.133
daemonize yes
pidfile 7003.pid
cluster-enabled yes
cluster-config-file 7003_node.conf
cluster-node-timeout 15000
appendonly yes
port 7004
bind 192.168.220.133
daemonize yes
pidfile 7004.pid
cluster-enabled yes
cluster-config-file 7004_node.conf
cluster-node-timeout 15000
appendonly yes
port 7005
bind 192.168.220.133
daemonize yes
pidfile 7005.pid
cluster-enabled yes
cluster-config-file 7005_node.conf
cluster-node-timeout 15000
appendonly yes
使用配置文件启动redis服务
redis-server /usr/local/redis/etc/conf/7003.conf
redis-server /usr/local/redis/etc/conf/7004.conf
redis-server /usr/local/redis/etc/conf/7005.conf
-
创建集群
redis的安装包重包含了redis-trib.rb, 用于创建集群
在192.168.220.132机器上进行,找到redis源码安装包
cp redis-stable/src/redis-trib.rb /usr/local/redis/bin
安装ruby环境,因为redis-trib.rb是用ruby开发的
yum install -y ruby
redis5.0使用redis-cli作为创建集群的命令,使用c语言实现,不再使用ruby语言。
因此无需使用 redis-trib.rb 文件,直接使用redis-cli
创建集群
redis-trib.rb create --replicas 1 192.168.220.132:7000 192.168.220.132:7001 192.168.220.133:7002 192.168.220.133:7003 192.168.220.134:7004 192.168.220.134:7005
redis-cli --cluster create 192.168.220.132:7000 192.168.220.132:7001 192.168.220.133:7002 192.168.220.133:7003 192.168.220.134:7004 192.168.220.134:7005 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.220.133:7003 to 192.168.220.132:7000
Adding replica 192.168.220.134:7005 to 192.168.220.133:7002
Adding replica 192.168.220.132:7001 to 192.168.220.134:7004
M: cb6d97578ad557a6ab5acfd5a49f8ee1cf10d53e 192.168.220.132:7000
slots:[0-5460] (5461 slots) master
S: ccc9f32340c96ef86e38728f2c5f1a690301273f 192.168.220.132:7001
replicates e841619eaf26e340a3e707295a0abf59feb6a469
M: c30c612e164c9203f4a2efb1dc63c951572ad417 192.168.220.133:7002
slots:[5461-10922] (5462 slots) master
S: 944e29825311f57384e93dcedd153b5bbf0e9ddc 192.168.220.133:7003
replicates cb6d97578ad557a6ab5acfd5a49f8ee1cf10d53e
M: e841619eaf26e340a3e707295a0abf59feb6a469 192.168.220.134:7004
slots:[10923-16383] (5461 slots) master
S: fb9e3cc8e101e93da5d4ccea8153ebfbd6435085 192.168.220.134:7005
replicates c30c612e164c9203f4a2efb1dc63c951572ad417
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.....
>>> Performing Cluster Check (using node 192.168.220.132:7000)
M: cb6d97578ad557a6ab5acfd5a49f8ee1cf10d53e 192.168.220.132:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: e841619eaf26e340a3e707295a0abf59feb6a469 192.168.220.134:7004
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 944e29825311f57384e93dcedd153b5bbf0e9ddc 192.168.220.133:7003
slots: (0 slots) slave
replicates cb6d97578ad557a6ab5acfd5a49f8ee1cf10d53e
M: c30c612e164c9203f4a2efb1dc63c951572ad417 192.168.220.133:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: fb9e3cc8e101e93da5d4ccea8153ebfbd6435085 192.168.220.134:7005
slots: (0 slots) slave
replicates c30c612e164c9203f4a2efb1dc63c951572ad417
S: ccc9f32340c96ef86e38728f2c5f1a690301273f 192.168.220.132:7001
slots: (0 slots) slave
replicates e841619eaf26e340a3e707295a0abf59feb6a469
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
数据验证
[root@k8s-node1 ~]# redis-cli -c -h 192.168.220.132 -p 7000
192.168.220.132:7000> keys *
(empty array)
192.168.220.132:7000> set name zhangsan
-> Redirected to slot [5798] located at 192.168.220.133:7002
OK
192.168.220.133:7002> get name
"zhangsan"
[root@k8s-node2 ~]# redis-cli -c -h 192.168.220.134 -p 7004
192.168.220.134:7004>
192.168.220.134:7004> get name
-> Redirected to slot [5798] located at 192.168.220.133:7002
"zhangsan"
192.168.220.133:7002> keys *
1) "name"
192.168.220.133:7002>
在哪个服务器上写数据:CRC161
redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
Redis集群没有使用传统的一致性哈希来分被数据,而是采用另一种叫做哈希槽(hash slot)的方式来分配的。redis cluster默认分配了16384个slot,当我们set一个key时,会用CRC16算法来取模得到所属的slot,然后将这个key分到哈希槽区间的节点上,具体的算法上就是:CRC16(key) % 16384。所以我们在测试的时候看到set和get时,直接跳转到了7002端口的节点。
Redis集群会把数据存在一个master节点,然后在这个master和其对应的slave之间进行数据同步。当读取数据时,也根据一致性哈希算发到对应的master节点获取数据。只有当一个master挂掉之后,才会启动一个对应的slave节点,充当master
需要注意:必须使用3个或以上的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总结点数的一半时,整个集群就无法提供服务了。
与Python交互
安装包如下:pip install redis-py-cluster
redis-py-cluster源码地址( http://github.com/Grokzen/redis-py-cluster)
创建文件redis_cluster.py,示例代码如下
from rediscluster import *
if __name__ == '__main__':
try:
# 构建所有的节点,Redis会使用CRC16算法,将键和值写到某个节点上
startup_nodes = {
{'host': '192.168.220.132','port':'7000'},
{'host': '192.168.220.133','port':'7002'},
{'host': '192.168.220.134','port':'7004'},
}
# 构建StrictRedisCluster对象
src = StrictRedisCluster(startup_nodes=startup_nodes, decode_response=True)
# 设置键为name,值为zhangsan的数据
result = src.set('name', 'zhangsan')
print(result)
# 获取键为name
name = src.get('name')
print(name)
except Exception as e:
print(e)