redis
redis 持久化功能
1、RDB
RDB是基于快照的一种持久化功能,保存某个时间点的,key:value状态。
dbfilename dump.rdb
dir /data/redis
save 900 1
save 300 10
save 60 10000
优点:
快速持久化,
占用磁盘空间少,
一般备份是通过RDB实现的,
主从复制功能也是通RDB功能实现的。
缺点:
当断电,重启时,RDB会丢失少部分数据。
2、AOF
appendonly LogFile,追加模式的日志记录持久化方式。会记录redis中所有变更类的命令。
appendonly yes
appendfsync always
appendfsync everysec
优点:相对RDB来讲,更加安全了。
缺点:持久化速度相对较慢,需要更多的存储空间。
数据类型:
string
hash
list
set
sorted set
key:value
-----------------
key的通用操作:
KEYS * 查看KEY支持通配符
DEL 删除给定的一个或多个key
EXISTS 检查是否存在
RENAME 变更KEY名
TYPE 返回键所存储值的类型
EXPIRE\ PEXPIRE 以秒\毫秒设定生存时间
TTL\ PTTL 以秒\毫秒为单位返回生存时间
PERSIST 取消生存实现设置
--------------------
STRING
计数器的实现:
incr num 每次累计加1
decr num 每次累计减1
incrby num 10000 累计加10000
decrby num 10000 累计减10000
普通键值对操作:
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> mset id 101 name zhangsan age 20 gender m
OK
127.0.0.1:6379> keys *
1) "name"
2) "id"
3) "xyz"
4) "jishu"
5) "age"
6) "gender"
127.0.0.1:6379> mget id name age gender
1) "101"
增
set mykey "test" 为键设置新值,并覆盖原有值
getset mycounter 0 设置值,取值同时进行
setex mykey 10 "hello" 设置指定 Key 的过期时间为10秒,在存活时间可以获取value
setnx mykey "hello" 若该键不存在,则为键设置新值
mset key3 "zyx" key4 "xyz" 批量设置键
删
del mykey 删除已有键
改
append mykey "hello" 若该键并不存在,返回当前 Value 的长度
该键已经存在,返回追加后 Value的长度
incr mykey 值增加1,若该key不存在,创建key,初始值设为0,增加后结果为1
decrby mykey 5 值减少5
setrange mykey 20 dd 把第21和22个字节,替换为dd, 超过value长度,自动补0
查
exists mykey 判断该键是否存在,存在返回 1,否则返回0
get mykey 获取Key对应的value
strlen mykey 获取指定 Key 的字符长度
ttl mykey 查看一下指定 Key 的剩余存活时间(秒数)
getrange mykey 1 20 获取第2到第20个字节,若20超过value长度,则截取第2个和后面所有的
mget key3 key4 批量获取键
---------------------------------
Hash类型(字典)
hmset stu id 101 name zhangsan age 20 gender m
hgetall stu
hmget stu id name
HVALS stu
增
hset myhash field1 "s"
若字段field1不存在,创建该键及与其关联的Hashes, Hashes中,key为field1 ,并设value为s ,若存在会覆盖原value
hsetnx myhash field1 s
若字段field1不存在,创建该键及与其关联的Hashes, Hashes中,key为field1 ,并设value为s, 若字段field1存在,则无效
hmset myhash field1 "hello" field2 "world 一次性设置多个字段
删
hdel myhash field1 删除 myhash 键中字段名为 field1 的字段
del myhash 删除键
改
hincrby myhash field 1 给field的值加1
查
hget myhash field1 获取键值为 myhash,字段为 field1 的值
hlen myhash 获取myhash键的字段数量
hexists myhash field1 判断 myhash 键中是否存在字段名为 field1 的字段
hmget myhash field1 field2 field3 一次性获取多个字段
hgetall myhash 返回 myhash 键的所有字段及其值
hkeys myhash 获取myhash 键中所有字段的名字
hvals myhash 获取 myhash 键中所有字段的值
-----------------
List 列表
127.0.0.1:6379> lpush wechat "today is nice day!"
(integer) 1
127.0.0.1:6379> lpush wechat "today is bad day!"
(integer) 2
127.0.0.1:6379> lpush wechat "today is good day!"
(integer) 3
127.0.0.1:6379> lpush wechat "today is abc day!"
(integer) 4
127.0.0.1:6379> lpush wechat "today is xyz day!"
127.0.0.1:6379> LRANGE wechat 0 -1
1) "today is xyz day!"
2) "today is abc day!"
3) "today is good day!"
4) "today is bad day!"
5) "today is nice day!"
127.0.0.1:6379> LRANGE wechat -1 -2
(empty list or set)
127.0.0.1:6379> LRANGE wechat -2 -3
(empty list or set)
127.0.0.1:6379> LRANGE wechat -2 -1
1) "today is bad day!"
2) "today is nice day!"
127.0.0.1:6379> LRANGE wechat -2 -2
1) "today is bad day!"
127.0.0.1:6379>
127.0.0.1:6379> LINDEX wechat 2
"today is bad day!"
127.0.0.1:6379>
127.0.0.1:6379> LPOP wechat
"today is xyz day!"
增
lpush mykey a b 若key不存在,创建该键及与其关联的List,依次插入a ,b, 若List类型的key存在,则插入value中
lpushx mykey2 e 若key不存在,此命令无效, 若key存在,则插入value中
linsert mykey before a a1 在 a 的前面插入新元素 a1
linsert mykey after e e2 在e 的后面插入新元素 e2
rpush mykey a b 在链表尾部先插入b,在插入a
rpushx mykey e 若key存在,在尾部插入e, 若key不存在,则无效
rpoplpush mykey mykey2 将mykey的尾部元素弹出,再插入到mykey2 的头部(原子性的操作)
删
del mykey 删除已有键
lrem mykey 2 a 从头部开始找,按先后顺序,值为a的元素,删除数量为2个,若存在第3个,则不删除
ltrim mykey 0 2 从头开始,索引为0,1,2的3个元素,其余全部删除
改
lset mykey 1 e 从头开始, 将索引为1的元素值,设置为新值 e,若索引越界,则返回错误信息
rpoplpush mykey mykey 将 mykey 中的尾部元素移到其头部
查
lrange mykey 0 -1 取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
lrange mykey 0 2 从头开始,取索引为0,1,2的元素
lrange mykey 0 0 从头开始,取第一个元素,从第0个开始,到第0个结束
lpop mykey 获取头部元素,并且弹出头部元素,出栈
lindex mykey 6 从头开始,获取索引为6的元素 若下标越界,则返回nil
-----------------------
set 集合
127.0.0.1:6379> sadd lxl jnl pg ms mr abc xyz baoqiang yf
(integer) 8
127.0.0.1:6379> sadd jnl baoqiang yf xyz mr lxl
(integer) 5
127.0.0.1:6379> SINTER lxl jnl
1) "mr"
2) "baoqiang"
3) "xyz"
4) "yf"
127.0.0.1:6379> SDIFF lxl jnl
1) "jnl"
2) "abc"
3) "ms"
4) "pg"
127.0.0.1:6379> SDIFF jnl lxl
1) "lxl"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> SUNION jnl lxl
1) "baoqiang"
2) "pg"
3) "xyz"
4) "yf"
5) "lxl"
6) "mr"
7) "jnl"
8) "ms"
9) "abc"
127.0.0.1:6379> SINTERSTORE gthy lxl jnl
(integer) 4
127.0.0.1:6379> SMEMBERS gthy
1) "mr"
2) "baoqiang"
3) "yf"
4) "xyz"
127.0.0.1:6379>
------
有序集合
---------
发布订阅:
窗口1:
redis-cli -a 123
SUBSCRIBE fm1039 订阅单个频道
PSUBSCRIBE fm* 订阅多个频道
窗口2:
127.0.0.1:6379> PUBLISH fm1039 "hi!"
(integer) 1
127.0.0.1:6379> PUBLISH fm1039 "hi!"
(integer) 1
127.0.0.1:6379> PUBLISH fm1038 "hi!"
(integer) 1
127.0.0.1:6379> PUBLISH fm1037 "hi!"
(integer) 1
127.0.0.1:6379>
--------------------------------------------------------
vim Linux文本编辑工具
1、命令模式:
G 光标到达最后一行
10G 光标到到10行
3yy 复制3行
3dd 删除(剪切)
p 粘贴
dG 删除所有行
u 撤销到上次操作
^ 光标到达行首
$ 光标到达行尾
/ 查找关键字
2、编辑模式(插入模式)
a i o
3、末行模式(冒号模式)
:wq
---------------------------------------------------------
主从复制实现:
1、环境:
准备两个或两个以上redis实例
mkdir /data/638{0..2}
配置文件示例:
vim /data/6380/redis.conf
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6380
protected-mode no
vim /data/6381/redis.conf
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6381/redis.log"
dbfilename dump.rdb
dir /data/6381
protected-mode no
vim /data/6382/redis.conf
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile "/data/6382/redis.log"
dbfilename dump.rdb
dir /data/6382
protected-mode no
启动:
redis-server /data/6380/redis.conf
redis-server /data/6381/redis.conf
redis-server /data/6382/redis.conf
主节点:6380
从节点:6381、6382
2、开启主从:
6381/6382命令行:
redis-cli -p 6381
SLAVEOF 127.0.0.1 6380
redis-cli -p 6382
SLAVEOF 127.0.0.1 6380
3、查询主从状态
从库:
[root@db01 ~]# redis-cli -p 6382
127.0.0.1:6382> info replication
[root@db01 ~]# redis-cli -p 6381
127.0.0.1:6381> info replication
-----
redis-sentinel(哨兵)
1、监控
2、自动选主,切换(6381 slaveof no one)
3、2号从库(6382)指向新主库(6381)
-------------
sentinel搭建过程
mkdir /data/26380
cd /data/26380
vim sentinel.conf
port 26380
dir "/data/26380"
sentinel monitor mymaster 127.0.0.1 6380 1
sentinel down-after-milliseconds mymaster 5000
启动:
redis-sentinel /data/26380/sentinel.conf &
--------------------------------
windows安装redis新驱动
cd d:
d:
D:\>cd redis
D:\redis>python3 setup.py install
sentinel模式:
>>> from redis.sentinel import Sentinel
>>> sentinel = Sentinel([('127.0.0.1', 26379)], socket_timeout=0.1)
>>> sentinel.discover_master('mymaster')
>>> sentinel.discover_slaves('mymaster')
>>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
>>> master.set('foo', 'bar')
>>> slave.get('foo')
'bar'
---------------------------------
redis cluster
高性能:
1、在多分片节点中,将16384个槽位,均匀分布到多个分片节点中
2、存数据时,将key做crc16(key),然后和16384进行取模,得出槽位值(0-16383之间)
3、根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上
4、如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储
高可用:
在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof的功能,同时当主节点down,实现类似于sentinel的自动failover的功能。
规划、搭建过程:
6个redis实例,一般会放到3台硬件服务器
注:在企业规划中,一个分片的两个分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失。
端口号:7000-7005
1、安装集群插件
EPEL源安装ruby支持
yum install ruby rubygems -y
使用国内源
gem sources -l
gem sources -a http://mirrors.aliyun.com/rubygems/
gem sources --remove http://rubygems.org/
gem install redis -v 3.3.3
gem sources -l
或者:
gem sources -a http://mirrors.aliyun.com/rubygems/ --remove http://rubygems.org/
---
2、集群节点准备
mkdir /data/700{0..5}
vim /data/7000/redis.conf
port 7000
daemonize yes
pidfile /data/7000/redis.pid
loglevel notice
logfile "/data/7000/redis.log"
dbfilename dump.rdb
dir /data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
vim /data/7001/redis.conf
port 7001
daemonize yes
pidfile /data/7001/redis.pid
loglevel notice
logfile "/data/7001/redis.log"
dbfilename dump.rdb
dir /data/7001
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
vim /data/7002/redis.conf
port 7002
daemonize yes
pidfile /data/7002/redis.pid
loglevel notice
logfile "/data/7002/redis.log"
dbfilename dump.rdb
dir /data/7002
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
vim /data/7003/redis.conf
port 7003
daemonize yes
pidfile /data/7003/redis.pid
loglevel notice
logfile "/data/7003/redis.log"
dbfilename dump.rdb
dir /data/7003
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
vim /data/7004/redis.conf
port 7004
daemonize yes
pidfile /data/7004/redis.pid
loglevel notice
logfile "/data/7004/redis.log"
dbfilename dump.rdb
dir /data/7004
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
vim /data/7005/redis.conf
port 7005
daemonize yes
pidfile /data/7005/redis.pid
loglevel notice
logfile "/data/7005/redis.log"
dbfilename dump.rdb
dir /data/7005
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
启动节点:
redis-server /data/7000/redis.conf
redis-server /data/7001/redis.conf
redis-server /data/7002/redis.conf
redis-server /data/7003/redis.conf
redis-server /data/7004/redis.conf
redis-server /data/7005/redis.conf
[root@db01 ~]# ps -ef |grep redis
root 8854 1 0 03:56 ? 00:00:00 redis-server *:7000 [cluster]
root 8858 1 0 03:56 ? 00:00:00 redis-server *:7001 [cluster]
root 8860 1 0 03:56 ? 00:00:00 redis-server *:7002 [cluster]
root 8864 1 0 03:56 ? 00:00:00 redis-server *:7003 [cluster]
root 8866 1 0 03:56 ? 00:00:00 redis-server *:7004 [cluster]
root 8874 1 0 03:56 ? 00:00:00 redis-server *:7005 [cluster]
3、将节点加入集群管理
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
---------------------
redis的多API支持
python为例
tar xf Python-3.5.2.tar.xz
cd Python-3.5.2
./configure
make && make install
https://redis.io/clients
下载redis-py-master.zip
unzip redis-py-master.zip
cd redis-py-master
python3 setup.py install
安装redis-cluser的客户端程序
cd redis-py-cluster-unstable
python3 setup.py install
1、对redis的单实例进行连接操作
python3
>>>import redis
>>>r = redis.StrictRedis(host='localhost', port=6379, db=0,password='123')
>>>r.set('foo', 'bar')
True
>>>r.get('foo')
'bar'
--------------------
2、sentinel集群连接并操作
[root@db01 ~]# redis-server /data/6380/redis.conf
[root@db01 ~]# redis-server /data/6381/redis.conf
[root@db01 ~]# redis-server /data/6382/redis.conf
[root@db01 ~]# redis-sentinel /data/26380/sentinel.conf &
--------------------------------
## 导入redis sentinel包
>>> from redis.sentinel import Sentinel
##指定sentinel的地址和端口号
>>> sentinel = Sentinel([('localhost', 26380)], socket_timeout=0.1)
##测试,获取以下主库和从库的信息
>>> sentinel.discover_master('mymaster')
>>> sentinel.discover_slaves('mymaster')
##配置读写分离
#写节点
>>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
#读节点
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
###读写分离测试 key
>>> master.set('oldboy', '123')
>>> slave.get('oldboy')
'123'
----------------------
redis cluster的连接并操作(python2.7.2以上版本才支持redis cluster,我们选择的是3.5)
https://github.com/Grokzen/redis-py-cluster
3、python连接rediscluster集群测试
使用
python3
>>> from rediscluster import StrictRedisCluster
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
### Note: decode_responses must be set to True when used with python3
>>> rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc.set("foo", "bar")
True
>>> print(rc.get("foo"))
'bar'
----------------------