redis简介: node
一、Redis是一款开源的,ANSI C语言编写的,高级键值(key-value)缓存和支持永久存储NoSQL数据库产品。 二、Redis采用内存(In-Memory)数据集(DataSet)。 三、支持多种数据类型。 四、运行于大多数POSIX系统,如Linux、*BSD、OS X等。 五、做者:Salvatore Sanfilippo
拷贝的简介,要想看的话,本身百度,不少这里就不介绍了,直接进入主题。
redis安装:linux
redis安装yum:
yum安装 配置文件在etc下 redis.conf
yum install -y epel-release # 扩展源下载 yum install -y redis #安装 systemctl enable redis #开机自动启动 systemctl start pedis #启动redis
redis安装源码包:
下载地址http://download.redis.io/releases/ #下载 yum install -y lrzsz #这个包是上传工具 tar -zxvf redis-3.2.6.tar.gz #解压 cd redis-3.2.6 #进入 make # 有可能报错 redis编译报致命错误:jemalloc/jemalloc.h:没有那个文件或目录 解决 make MALLOC=libc cp redis.conf ../redis6380/ #配置文件 cp src/redis-server ../redis6380/ #启动文件 主程序 ./redis-server ./redis.conf #启动
配置文件说明redis
egrep -v "^#|^$" redis.conf > redis.conf2 #配置文件去除开头带#跟空行 方法有不少 怎么熟悉怎么来 mv redis.conf redis.conf_bak #备份原配置文件 mv redis.conf2 redis.conf #覆盖原配置文件 vim redis.conf #修改端口等信息
bind ip地址 #就在内网上开 protected-mode yes #启动安全机制 requirepass root #结合安全机制 设置密码 demonize yes #(配置文件里面参数 后台启动) pidfile /var/run/redis_6380.pid #pid文件 logfile "/data/redis6380/redis.log" #日志文件 port 6379 #端口 appendonly no -> yes #日志开关 记录数据变化的 持久化策略开关 logfile stdout -> ./logs/redis.log #日志错误文件 dbfilename dump.rdb #持久化数据文件。至关于数据库的数据文件 rdbcompression yes #压缩 这些都是经常使用的配置,有些配置能够在redis内部用命令来设置
/usr/lib/systemd/system/redis.ervice (yum 安装的有 源码包安装没有)
简单的多实例数据库
复制这个目录 修改端口 就是多实例 drwxr-xr-x 2 root root 96 7月 19 22:27 redis6380 drwxr-xr-x 2 root root 96 7月 19 22:31 redis6381
分别在这两个目录启动 tcp 0 0 127.0.0.1:6380 0.0.0.0:* LISTEN 13202/./redis-serve tcp 0 0 127.0.0.1:6381 0.0.0.0:* LISTEN 13228/./redis-serve
redis保护机制vim
修改完配置文件redis.conf protected-mode yes #启动安全机制 requirepass root #结合安全机制 设置密码
例子: 127.0.0.1:6380> get foo #须要认证 (error) NOAUTH Authentication required 127.0.0.1:6380> auth root #我来认证 OK 127.0.0.1:6380> get foo #成功 "guohongze"
持久化|策略缓存
RDB 持久话能够在指定时间间隔内生成数据集的时间点快照(point-in-time-snapshot) AOF 持久化记录服务器执行的全部写操做的命令,并服务器启动时,经过从新执行这些命令来还原数据集。 save 900 1 save 300 10 save 60 10000 900秒(15分钟) 有一次操做的话 就保存一次 300秒(5分钟) 有十次操做的话 就保存一次 60秒(1分钟) 有10000次操做的话 就保存一次
同步安全
配置文件redis.conf appendfsync everysec no 表示等操做系统进行数据缓存同步到磁盘上linux约30秒 always 即是每次更新操做后调用fsunc()将数据写到磁盘 (慢 安全) everysec 表示每秒同步一次 (折中,默认值) 后期 优化能够考虑调整这些参数
redis高级应用 队列 | 订阅ruby
发布消息一般有两种模式:(队列模式queuing 和发布-订阅模式publish-subscribe) 队列模式: consumers(消费者)能够同时从服务器端读取消息,每一个消息只被其中一个consumer(消费者)读到。 发布-订阅模式: 中消息被广播到全部consumer(消费者)中,topic中的消息将被分发到组中的一个成员中。 同一组中的consumer能够在不一样的程序中,也能够在不一样的机器上。 队列模式例子: 127.0.0.1:6380> lrange bao 0 10 1) "bao6" 2) "bao5" 3) "bao4" 4) "bao3" 5) "bao2" 6) "bao1" 7) "bao" 127.0.0.1:6380> rpop bao #删除一个 "bao" 127.0.0.1:6380> rpop bao "bao1" 127.0.0.1:6380> rpop bao "bao2" 127.0.0.1:6380> lrange bao 0 10 #查看 1) "bao6" 2) "bao5" 3) "bao4" 4) "bao3" 127.0.0.1:6380> lpush bao bao7 #添加 (integer) 5 127.0.0.1:6380> lpush bao bao8 (integer) 6 127.0.0.1:6380> lpush bao bao9 (integer) 7 127.0.0.1:6380> lrange bao 0 10 1) "bao9" 2) "bao8" 3) "bao7" 4) "bao6" 5) "bao5" 6) "bao4" 7) "bao3" 先进先出 发布订阅模式: 发布订阅(pub/sub)是一种消息通信模式:发送者(pud)发送消息,订阅者(sub)接收消息 redis 客户端能够订阅任意数量的频道 两台client端同时订阅 client1命令:subscribe wanghong #订阅网红 关注一个频道 网红频道 127.0.0.1:6380> SUBSCRIBE mq1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "mq1" 3) (integer) 1 1) "message" 2) "mq1" 3) "qing guan zhu wo " #这条消息是redis服务器端发布以后出现的 client2命令:subscribe wanghong 被订阅端发布一个消息 server命令:publish mq1 “qing guangzhu wo” 127.0.0.1:6380> publish mq1 "qing guan zhu wo " (integer) 2
redis事物bash
Redis 事务能够一次执行多个命令 事务是一个单独的隔离操做:事务中的全部命令都会序列化、按顺地执行。 事务在执行的过程当中,不会被其余客户端发送来的命令请求所打断。 原子性:事务命令要么所有被执行,要么就所有都不执行 执行过程 开始事务 命令入队 执行事务 127.0.0.1:6380> ZADD salary 3000 guohongze 5000 oldboy 建立一个zadd的有序 集合 (integer) 2 127.0.0.1:6380> multi #标记一个事务块的开始 OK 127.0.0.1:6380> zincrby salary 1000 guohongze #添加事务一 guohongze加1000 QUEUED 127.0.0.1:6380> zincrby salary -1000 oldboy #添加事务二 oldboy减1000 QUEUED 127.0.0.1:6380> exec #执行全部事务块内的命令 1) "4000" 2) "4000" 127.0.0.1:6380> ZRANGE salary 0 -1 withscores #看一下有序集合的数据 1) "guohongze" 2) "4000" 3) "oldboy" 4) "4000" ####保证数据的一致性
redis慢日志查询服务器
Slowlog 是redis用来记录查询执行时间的日志系统 Slowlog 保存在内存里面,读写速度很是快 能够经过改写redis.conf文件 后者 config get 和config set命令对他们动态地修改 slowlog-log-slower-than 10000 #超过多少微秒 #配置文件设置 config set slowlog-log-slower-then 100 #里面设置 config set slowly-max-len 1000 #保存多少条慢日志 Config get slow* #查询 Slowly get Slowly reset
redis数据备份
config get dir 获取当前目录 Save 备份(无持久化策略时),生成时在redis当前目录中。 恢复时只需将dump.db放入redis当前目录 (放入时候须要redis未启动,备份文件有数据或者在当前目录下,方可启动redis主程序) 当配置文件持久化关闭时(appendonly no)redis须要手动保存 直接save 就是产生dump.rdb 文件
redis复制(Replication)
config get dir 获取当前目录 Save 备份(无持久化策略时),生成时在redis当前目录中。 恢复时只需将dump.db放入redis当前目录 (放入时候须要redis未启动,备份文件有数据或者在当前目录下,方可启动redis主程序) 当配置文件持久化关闭时(appendonly no)redis须要手动保存 直接save 就是产生dump.rdb 文件 ------------redis复制(Replication)----------- 在从服务器删除旧版本数据集并载入新版本的数据集的那段时间内,连接请求会被阻塞 能够经过复制功能来让主服务器免于执行持久化操做,只要关闭主服务器的持久化功能,而后由从服务器去执行持久化操做便可。 避免一个问题: 1.假设节点A为主服务器,而且关闭了持久化,而且节点B和节点C从节点A复制 2.节点A崩溃,而后由自动拉起服务重启了节点A,因为节点A的持久化被关闭,因此重启以后没有任何数据 3.节点B和节点C将从节点A复制数据,可是A节点的数据是空的,因而就把自身保存的数据副本删除了 解决办法:没有自动拉起服务就行了 ------注意 积压空间问题---: 初次连接仍是从新连接,当创建一个从服务器时,从服务器都将向主服务器发送一个sync命令。 接到sync命令的主服务器将开始bgsave,并在保存操做执行期间,将全部新执行的写入命令都报错到一个缓冲区里面。 当gbsave执行完毕后,主服务将执行保存操做所得的.rdb 文件发送给从服务器,从服务器接受这个.rdb文件,并将文件中的 数据载入到内存中 --------配置-------: 1。只须要在配置文件中增长一行: slaveof 192.168.1.1 6379 其中 92.168.1.1 和 6379 替换成你的主服务器的ip和端口 坏处:崩溃了 不敢重启 2.调用命令 slaveof 192.168.1.1 6379 便可 其中 92.168.1.1 和 6379 替换成你的主服务器的ip和端口 好处 你要重启了 手动命令 slaveof no one 将从变成主 ------手工主从切块------- 在原来的主上面关闭redis 在第一个从上面 slaveof no one 在第二台从 上面 添加 slaveof 192.168.1.1 6379 第一台从服务器的ip和端口 若是第一台开启了 那就成了从服务器了
redis sentinel(哨兵)
sentinel是redis官方推荐的高可用(HA)解决方案 1。监控(monitoring)Sentinel不断地检查你的主服务器和从服务器是否运做正常 2.提醒(notification)当被监控的某个redis服务器出现问题时,Sentinel可经过API向管理员或者其余应用程序发送通知。 3.自动故障迁移(Automatic failover):当一个主服务器不能正常工做时候,Sentinel会开始一次自动故障迁移操做,他会将失效主服务器的器中一个从服务升级为新的主服务器,并让失效的主服务器的其余从服务器改成复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可使用新主服务器代替失效服务器 mkdir S1 #建立一个目录 cp redis-3.2.6/sentinel.conf /data/S1/ #配置文件 cp redis-3.2.6/src/redis-sentinel /data/S1/ #主程序文件 sentinel 端口26379 -------------sentinel.conf配置文件---- sentinel monitor mymaster 127.0.0.1 6381 1 #有两个sentinel 最后的是2集群参数 sentinel auth-pass mymaster luyx30 #安全信息 sentinel down-after-milliseconds mymaster 10000 #1万毫秒 当主从切换多久后认为主从切换失败 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 启动 ./redis-sentinel ./sentinel.conf 修改端口号 还有sentinel monitor mymaster 127.0.0.1 6381 2 最后一个参数修改为2
redis集群
Redis集群时一个能够在多个redis节点之间进行数据共享的设施(installation) Redis集群不支持那些须要同时处理多个键的redis命令,由于执行这些命令须要在多个redis节点之间移动数据,而且在高负载的状况下,这些命令将下降redis群集的性能,并致使不可预测的行为 Redis集群经过分区(partition)来提供必定程度的可用性(rvailability):即便集群中有一个部分节点失效后者没法进行通讯,集群也能够继续处理命令请求 将数据自动切分(split)到多个节点的能力 当集群中的一部分节点失效或者没法进行通讯时,仍然能够继续处理命令请求的能力 安装集群 16383个哈希槽 Yum install ruby rubygems -y gem install redis 若是卡住了使用国内镜像 gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org gem sources -l 配置文件redis.conf port 7000 #端口 cluster-enabled yes # cluster-node-timeout 5000 appendonly yes pidfile "/var/run/redis.pid" dir "./" 复制六个实例 for no in 0 1 2 3 4 5;do cp -r redis6380/ 700$no;done #复制实例 修改配置文件(这里有一个脚本) #!/bin/bash rm -rf /data/700* for no in 0 1 2 3 4 5;do cp -r redis6380/ 700$no;done for no in 0 1 2 3 4 5;do rm -rf /data/700$no/dump.rdb;done for no in 0 1 2 3 4 5 do cd /data/700$no sed -i "s/port 6380/port 7000/g" redis.conf echo "cluster-enabled yes" >> redis.conf echo "cluster-config-file nodes.conf" >> redis.conf echo "cluster-node-timeout 5000" >> redis.conf sed -i "s/appendonly no/appendonly yes/g" redis.conf sed -i "s/redis_6380.pid/redis_700$no.pid/g" redis.conf sed -i "s/^dir/d" redis.conf echo 'dir "./"' >>Reds.conf done for no in 0 1 2 3 4 5;do cd /data/700$no && ./redis-server ./redis.conf;done #启动 建立集群的命令: /data/redis-3.2.6/src/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 #--replicas 1 #几个从服务器 当前是一个 1.给定redis-trib.rb 程序的命令是create 这个表示咱们但愿建立一个新的集群 2.选项 --replicas 1 表示咱们但愿为集群中的每一个主节点建立一个从节点 3.以后跟着的其余参数 则是实例的地址列表,咱们但愿程序使用这些地址所指示的实例来建立新集群 登录集群 redis-cli -c -p 7000 # 必须加c 不加c参数登录进去是有问题的 不加c是单机 集群状态 redis-cli -p 7000 cluster nodes |grep master 故障转移 redis-cli -p 7002 debug segfault 查看状态 redis-cli -p 7000 cluster nodes |grep master 从新分片 redis-trib.rb reshard 127.0.0.1:7000
命令
Redis-cli -p 6379 #进入(yum安装/usr/bin/redis ) 127.0.0.1:6380> set foo guohongze #建立一个键值对 127.0.0.1:6380> get foo #取出foo 对应的 值 127.0.0.1:6380> keys * #获取全部的key [root@localhost redis6380]# /data/redis-3.2.6/src/redis-cli -p 6380 #进入(源码安装) 127.0.0.1:6380> SHUTDOWN #中止服务 not connected> exit #退出
127.0.0.1:6380> auth root #我来认证 一种保护数据机制
关于redis配置命令
Info 服务器信息 client list 查看有一个客户端 client kill IP:port config get * config resetstat 重置统计 config get/set 动态修改 Dbsize flushall 清空全部数据 select 1 flushDB 清空当前库 Monitor 监控实时指令 最为经常使用 shutdown 关闭服务器 Save 将当前数据保存 slaveof host port 主从配置 slaveof no ond Sync 主从同步 Role 返回主从角色
redis一些简单的练习
------------------------字符串------------------------- ------set|get|type--- 127.0.0.1:6380> set name goujongze #建立一个name的键值对 OK 127.0.0.1:6380> get name #get name "goujongze" 127.0.0.1:6380> type name #查看类型 string 127.0.0.1:6380> 一个key 对应的值 最大能储存512MB ----append----- 127.0.0.1:6380> APPEND name 123 # 在值的尾部多加一个值 (integer) 12 127.0.0.1:6380> get name "goujongze123" ----Mset------- 127.0.0.1:6380> MSET name guohongze foo oldboy #同时设置一个或者多个键值对 OK 127.0.0.1:6380> MGET name foo 1) "guohongze" 2) "oldboy" 127.0.0.1:6380> ----strlen------- 127.0.0.1:6380> strlen name #字符串长度 (integer) 9 127.0.0.1:6380> get name "guohongze" 127.0.0.1:6380> ----incr|decr|incrby|decrby------- 127.0.0.1:6380> set age 33 OK 127.0.0.1:6380> 127.0.0.1:6380> INCR age #incr 加一 decr 减一 (integer) 34 127.0.0.1:6380> INCR age (integer) 35 127.0.0.1:6380> decr aghe (integer) -1 127.0.0.1:6380> decr aghe (integer) -2 127.0.0.1:6380> incrby age 100 #incrby|decrby 加一百 减一百 (integer) 137 127.0.0.1:6380> DECRBY age 100 (integer) 37 ----EXISTS------- 127.0.0.1:6380> EXISTS name #检查name是否存在 1 是存在 0 不存在 (integer) 1 127.0.0.1:6380> EXISTS asdasd (integer) 0 127.0.0.1:6380> ------------------------hash(哈希)------------------------- Redis hash 是一个键值对集合 Redis hash是一个string类型的field和value的映射表 Hash特别适合用于储存一个对象 每一个hash能够储存 2^32-1 键值对 ----------hset| hgetall|hget| hget---------- 127.0.0.1:6380> hset user:1 name gouhongze #设置一个user:1对象 (integer) 1 127.0.0.1:6380> type user:1 hash 127.0.0.1:6380> hset user:1 age 35 (integer) 1 127.0.0.1:6380> hset user:1 sex male (integer) 1 127.0.0.1:6380> hgetall user:1 #get user:1 这个对象全部值 1) "name" 2) "gouhongze" 3) "age" 4) "35" 5) "sex" 6) "male" 127.0.0.1:6380> hget user:1 age #get 一个age 值 "35" 127.0.0.1:6380> hget user:1 name #get 一个name 值 "gouhongze" 127.0.0.1:6380> hmget user:1 name age #get 两个值 1) "gouhongze" 2) "35" --——————————---del---——————————————————--- 127.0.0.1:6380> keys * 1) "user:1" 2) "foo" 3) "name" 4) "aghe" 5) "oldboy" 6) "age" 127.0.0.1:6380> del oldboy #删除一个 (integer) 1 127.0.0.1:6380> keys * 1) "user:1" 2) "foo" 3) "name" 4) "aghe" 5) "age" --------------hdel-------————————————-- 127.0.0.1:6380> hdel user:1 age. #删除user:1 里面的age (integer) 1 127.0.0.1:6380> hgetall user:1 1) "name" 2) "xiaoqi" 3) "sex" 4) "male" ------------------------list(列表)------------------------- Redis列表是简单的字符串列表 按照插入顺序排序每一个 List能够存储2^32-1 键值队 -------lpush|lrange----- 127.0.0.1:6380> LPUSH list1 bmw benz toyota honda #建立一个list1 (integer) 4 127.0.0.1:6380> type list1 #查看类型 list 127.0.0.1:6380> LRANGE list1 0 10 #便利一个列表 0是开始位 10结束位 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" 127.0.0.1:6380> lpush list1 volvo #前面插入数据 (integer) 5 127.0.0.1:6380> rpush list1 byd #后面插入数据 (integer) 6 127.0.0.1:6380> lrange list1 0 10 #遍历一个list 1) "volvo" 2) "honda" 3) "toyota" 4) "benz" 5) "bmw" 6) "byd" -------rpop|lpop------- 127.0.0.1:6380> lrange list1 0 10 1) "volvo" 2) "honda" 3) "toyota" 4) "benz" 5) "bmw" 6) "byd" 127.0.0.1:6380> rpop list1 #最后的一个删除 "byd" 127.0.0.1:6380> lpop list1 #最前的一个删除 "volvo" 127.0.0.1:6380> LRANGE list1 0 10 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" ----llen---- 127.0.0.1:6380> llen list1 #list长度 (integer) 4 127.0.0.1:6380> lrange list1 0 10 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" -----------lrem-------- 127.0.0.1:6380> lrange list1 0 10 1) "bao8" 2) "bao7" 3) "bao6" 4) "bao6" 5) "bao5" 6) "bao4" 7) "bao3" 8) "bao2" 127.0.0.1:6380> lrem list1 1 bao6 #1数量 删除bao6 (integer) 1 127.0.0.1:6380> lrange list1 0 10 1) "bao8" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao4" 6) "bao3" 7) "bao2" ------lset------ 127.0.0.1:6380> lset list1 0 baozi001 修改list里面索引为0的元素 OK 127.0.0.1:6380> lrange list1 0 10 1) "baozi001" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao4" 6) "bao3" 7) "bao2" ------lindex------ 127.0.0.1:6380> lindex list1 0 "baozi001" --------linsert----- 127.0.0.1:6380> LINSERT list1 after bao5 bao6 #在baozi5后面插入baozi6 (integer) 8 127.0.0.1:6380> lrange list1 0 10 1) "baozi001" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao6" 6) "bao4" 7) "bao3" 8) "bao2"