zoukankan      html  css  js  c++  java
  • 学习Redis(一)

    一、NoSQL

    1、NoSql介绍

    1、not only SQL,非关系型数据库,它能解决常规数据库的并发、IO与性能的瓶颈
    2、解决以下问题:
    ① 对数据库的高并发读写需求
    ② 大数据的高效存储和访问需求
    ③ 高可扩展性和高可用性的需求

    2、Nosql数据库的应用环境

    1) 数据模型比较简单
    2) 需要灵活性更强的IT系统
    3) 对数据库的性能要求较高
    4) 不需要高度数据一致性
    5) 对于给定KEY,比较容易映射复杂值的环境

    3、Nosql软件的分类与特点

    1、key-value键值存储数据库
    1) 介绍
    ① 键值对存储,可通过key来添加、查询、删除数据
    ② 用于内容缓存,适合负载并扩展大的数据集
    ③ 数据类型是一系列的键值对
    ④ 有快速查询功能,但存储数据少结构化
    ⑤ 对事务的支持不好,数据库故障产生时不可进行回滚
    2) 常见数据库产品
    redis、memcached、ttserver   
    3) 应用场景
    存储用户信息,如会话、配置文件、参数、购物车、计数(统计粉丝关注)等
    
    2、列存储数据库     
    1) 介绍
    ① 查询多个列
    ② 用于分布式的文件系统
    ③ 以列簇式存储,将同一列数据存在一起
    ④ 查找速度快,可扩展强,更容易进行分布式扩展
    ⑤ 功能相对局限
    2) 常见数据库产品
    HBase
    3) 适用场景
    日志(将信息写入自己的column family中)
    blog平台(存储到不同的column family中,如标签、类别、文章等)
    
    3、面向文件的数据库 
    1) 介绍
    ① 版本化的文档,半结构化的文档
    ② 用于WEB应用较多
    ③ 数据类型是一系列键值对
    ④ 查询性能不高,没有统一的查询语法
    2) 常见数据库产品
    mongoDB
    3) 适用场景
    日志(程序有不同的日志)
    无固定的模式,存储不同的信息
    分析(不改变模式,就可存储不同的度量方法,及添加新的度量)
    
    4、图形数据库 
    1) 介绍
    ① 数据已图的方式存储
    ② 社交网络应用较多
    ③ 不容易做分布式的集群方案
    2) 常见数据库产品
    Graph
    3) 适用场景
    在关系型强的数据中,推荐引擎,社交网络,推荐系统等

    4、常用的Nosql数据库介绍

    1、memcached
    1) 介绍
    一个开源高性能的,具有分布式内存对象的缓存系统
    2) 特点
    ① 安装布署简单
    ② 支持高并发、高性能
    ③ 通过程序或负载均衡可以实现分布式
    ④ 仅为内存缓存,重启服务数据丢失
    
    2、memcacheDB
    1) 介绍
    新浪基于memcached开发的一个开源项目,具备了事务恢复功能
    2) 特点
    ① 高并发读写
    ② 高效存储
    ③ 高可用数据存储
    
    3、ttserver(tokyo tyrant/tokyocabinet)
    1) 介绍
    日本开发的DBM数据库,读写非常快,是BDB的几倍
    2) 特点
    ① 支持内存缓存,可持久化存储
    ② 故障转移,tokyo tyrant支持主从模式,双机互为主从模式,主从库均可读写
    ③ 5千万条数据,级别内的访问相当快
    ④ 兼容memcached协议,客户端不需更改任何代码
    
    4、mongoDB(document-oriented)
    1) 介绍
    一个基于分布式文件存储的数据库,由C++语言编写
    2) 特点
    易部署、高性能、易使用、存储数据非常方便
    
    5、redis(key-value)
    1) 介绍
    用ANSIC语言编写(代码3W多行),基于内存及持久化日志型、Key-Value数据库,提供多种语言的API
    2) 特点
    ① 支持内存缓存,相当于memcached
    ② 持久化,相当于memcachedb,ttserver
    ③ 数据类型更丰富
    ④ 支持集群,分布式

    5、生产环境如何选择Nosql数据库

    1、最常规的缓存应用,memcached最合适
    2、持久化存储方案,用memcacheDB
    3、2000万以内数据量的小数据,用memcached
    4、大数据量,用redis

    二、redis

    1、redis网站

    http://www.redis.cn/
    http://www.redis.io/topics/introduction

    2、redis特点

    1、key-value键值类型存储
    2、支持数据可靠存储
    3、单进程单线程高性能服务器
    4、恢复比较慢
    5、单机qps(秒并发)可以达到10W
    6、适合小数据量高速读写访问

    3、redis持久化

    1、介绍
    redis将数据存储内存中,通过快照、日志两种方式实现持久化存储
    
    2、持久化对比 snapshot(快照): 一次性将内存中的数据写入到磁盘,会导致数据的丢失 aof : 类似MySQL的binlog日志,记录每次更新的日志,不用于主从同步,仅能保存数据
    3、配置文件对比 Snapshot(快照) save 900 1 #900秒有1个key,则触发快照写入磁盘 save 300 10 save 60 10000 AOF(更新日志) appendfsync always #总是记录更新内容 appendfsync everysec #每秒记录更新内容 appendfsync no #不记录更新内容

    4、 redis的数据类型

    String          字符串
    Hash            哈希表
    List            列表
    Set             集合
    Sorted set      有序集合

    5、redis应用场景

    1、计数器、好友关系、cache服务
    2、微博(评论、转发、阅读、赞等),用户(粉丝、关注、收藏等)
    3、用户最近访问记录、最热,点击率最高,活跃度最高的视频或帖子

    6、redis的生产经验

    1、要配置主从同步,在出现故障时可以切换
    2、master禁用持久化,slave配置数据持久化
    3、物理内存 + 虚拟内存不足,这时dump一直死着,时间久了机器会挂掉
    4、当redis物理内存,使用超过内存总容量的3/5时,就开始做swap,比较危险,内存碎片大
    5、当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间
    6、redis与db同步写的问题,先写db,后写redis

    三、redis部署

     1、安装redis

    # wget http://download.redis.io/releases/redis-2.8.24.tar.gz
    # tar zxf redis-2.8.24.tar.gz
    # cd redis-2.8.24
    # make
    # make PREFIX=/application/redis-2.8.24 install

    2、相关命令

    redis-server                                            #服务器命令
    redis-cli                                               #客户端命令,也可以用telnet连接
    redis-benchmark                                         #性能测试工具,测试读写性能
    redis-check-aof                                         #检查aof日志文件
    redis-check-dump                                        #检查本地rdb快照文件

    3、启动服务

    1、查看命令帮助
    # redis-server -h
    
    2、复制配置文件
    # cp  redis-2.8.24/redis.conf   /application/redis/conf/
    
    3、启动服务
    # redis-server /application/redis/conf/redis.conf 
    
    4、关闭服务
    # redis-cli   shutdown
    # redis-cli   shutdown save
    
    5、警告处理
    1) 参数说明(vm.overcommit_memory)
      0: 应用请求更多内存时,内核检查是否有足够的内存,若有,分配应用,若无,不分配,返回错误给应用
      1: 内核允许分配所有的内存,不管内存状态(主要用于科学计算)
      2: 内核绝不过量使用内存,即系统整个内存不能超过swap+50%的RAM值,50%在overcommit_ratio中设定
    2) 永久生效
    # echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
    # sysctl -p 
    3) 临时生效
    # sysctl vm.overcommit_memory=1
    # echo '1' > /proc/sys/vm/overcommit_memory

    4、相关命令

    # redis-cli                                             #连接本地redis
    6379> set id 001                                        #设置key和value
    6379> get id                                            #取key的值
    6379> del id                                            #删除key
    6379> exists id                                         #验证key是否存在
    6379> keys *                                            #查看所有的key
    6379> select 1                                          #切换到库1模式(默认有16个库,可在配置文件设置)

    5、redis远程连接和非交互式操作 

    1、远程连接
    # redis-cli -h 10.0.0.135 -p 6379
    
    2、远程连接并执行命令
    # redis-cli -h 10.0.0.135 -p 6379 set aaa 111
    # redis-cli -h 10.0.0.135 -p 6379 get aaa
    
    3、其他命令连接方式
    # telnet 10.0.0.135 6379
    # echo "set no004 zsq" |nc 127.0.0.1 6379
    # echo "get no004 "    |nc 127.0.0.1 6379

    6、redis命令帮助 

    1、客户端命令帮助:
    6379> ?                                                 #查看帮助命令用法
    6379> help                                              #查看帮助命令用法
    6379> help set                                          #查看set命令用法
    
    2、通过help命令来查找命令
    6379> help @generic                                     #需要多次按Tab键
          help + 空格 + 多次<Tab>键来切换所有命令

    7、redis安全

    1、设置密码      
    redis没有用户概念,1秒可尝试上万次的密码登陆,要设置复杂的密码,来防止暴力破解
    1) 方法一:
    # vim  redis.conf
      requirepass  "123456"                                 #设置密码
    2) 方法二:
    # redis-cli 
    6379> config set requirepass 123456
    6379> config rewrite
    3) 登陆方法一:
    # redis-cli 
    6379> auth 123456      
    4) 登陆方法二:
    # redis-cli -a 123456    
    
    2、屏蔽危险命令(命令改名)
    # vim redis.conf
      rename-command set "sset"                             #将set修改为sset 
      rename-command keys ""                                #屏蔽掉keys命令

     8、安装redis客户端(php环境) 

    1、获取源码包
    # wget https://github.com/nicolasff/phpredis/archive/master.zip
    
    2、安装
    # unzip    phpredis-master.zip
    # cd       phpredis-master
    # /application/php/bin/phpize
    # ./configure --with-php-config=/application/php/bin/php-config
    # make && make install
    
    3、检查
    # ls /application/php-5.6.8/lib/php/extensions/no-debug-non-zts-20131226/
      memcache.so  opcache.a  opcache.so  redis.so
    
    4、修改设置
    # vim /application/php/lib/php.ini
      extension = redis.so 
      extension_dir = "/application/php-5.6.8/lib/php/extensions/no-debug-non-zts-20131226/" 
    
    5、重启php
    # killall php-fpm 
    # /application/php/sbin/php-fpm
    
    6、php操作redis
    # cat redis.php 
      <?php
         $redis = new Redis();
         $redis ->connect('10.0.0.135',6379);
         $redis ->auth('123456');
         $redis ->set('name','zhang3');
         $var = $redis ->get('name');
         echo "$var
    ";
      ?>

      9、安装redis客户端(Python)

    1、安装
    # wget https://pypi.python.org/packages/source/r/redis/redis-2.10.1.tar.gz
    # tar xf redis-2.10.1.tar.gz
    # cd redis-2.10.1
    # python setup.py install
    
    2、python操作redis
    # python
    >>> import redis                                        #导入redis库
    >>> r = redis.Redis(host='10.0.0.135',port='6379',password='123456') #连接redis(面向对象)
    >>> r.set('name','benet')                               #写入数据
    >>> r.get('name')                                       #读取数据
    >>> r.dbsize()                                          #查看数据数
    >>> r.keys()                                            #查看所有的key
    >>> exit()                                              #退出
    
    3、Web界面Python连接Redis
    1) 编写脚本
    # cat python-redis.py 
      #/usr/bin/python
      from wsgiref.simple_server import make_server
      import redis
    
      def get_redis():
          r = redis.Redis(host='10.0.0.135',port='6379',password='123456',db=0)
          r.set('name','zhang3')
          return r.get('name')
          
      def hello_world_app(environ,start_response):
          status = '200 OK'   
          headers = [('Content-type','text/plain')]   
          start_response(status,headers)
        
          return get_redis()
    
      httpd = make_server('',8000,hello_world_app)
      print "Serving on port 8000..."
    
      httpd.serve_forever()
    2) 启动python脚本
    # python python-redis.py
    3) 访问
    http://127.0.0.1:8000

    10、解读redis配置文件 

    # vim redis.conf
      include /path/to/local.conf                           #redis支持include功能
      daemonize no                                          #是否后台运行
      pidfile /var/run/redis.pid                            #pid文件的位置
      port 6379                                             #监听端口
      tcp-backlog 511                                       #tcp监听队列
      bind 10.0.0.135                                       #监听地址
      timeout 0                                             #客户端超时时间
      tcp-keepalive 0                                       #tcp的会话保持时间
      loglevel notice                                       #日志级别
      logfile ""                                            #日志记录位置,默认打印到屏幕上
      syslog-facility local0                                #是否启用syslog接收日志(日志集中收集)
      databases 16                                          #库的数量(默认为0到15)
      save  ""                                              #不保存快照
      save 900 1                                            #900秒有1个key,触发快照
      save 300 10                                           #300秒有10个key,触发快照
      save 60 10000                                         #60秒有10000个key,触发快照
      stop-writes-on-bgsave-error yes                       #bgsave出错是否停止写入
      dbfilename dump.rdb                                   #持久化文件名
      dir ./                                                #持久化文件位置(默认当前路径)
      rdbcompression no                                     #是否压缩rdb文件,会消耗cpu
      rdbchecksum yes                                       #检查rdb数据
      requirepass 123456                                    #redis的密码
      rename-command CONFIG ""                              #屏蔽命令
      rename=command get wk                                 #命令改名
      maxmemory 2G                                          #限制redis内存
      maxmemory-policy volatile-lru                         #内存清理的算法
      appendonly no                                         #是否启用AOF持久化
      appendfilename "appendonly.aof"                       #AOF文件名
      appendfsync everysec                                  #每秒记录
      auto-aof-rewrite-percentage 100                       #自动重写(rewrite)的百分比
      auto-aof-rewrite-min-size 64mb                        #自动重写(rewrite)aof的文件大小
      lua-time-limit 5000                                   #lua脚本最大运行时间
      hash-max-ziplist-entries 512                          #hash优化参数(数量512以下,数据压缩)
      hash-max-ziplist-value 64                             #hash优化参数(长度小于64字节,数据压缩)
      slaveof 10.0.0.135 6379                               #设置主从复制
      masterauth 123456                                     #主库密码
      requirepass 123456                                    #本身密码
      maxclients 128                                        #最大连接数
      vm-enabled no                                         #是否启用虚拟内存
      vm-swap-file /tmp/redis.swap                          #虚拟内存文件路径
      vm-max-memory 0                                       #所有大于vm-max-memory的数据,存入虚拟内存
      vm-page-size 32                                       #虚拟内存数据页的大小
      vm-pages 134217728                                    #虚拟内存数据页的数量
      vm-max-threads 4                                      #访问虚拟内存文件的线程数
      glueoutputbuf yes                                     #应答客户端时,是否合并较小的包
      activerehashing yes                                   #是否激活重置哈希

     四、redis数据类型

    1、String (字符串)

    1、介绍
    string类型是二进制,很安全的,一个key对应一个value,包含任何数据,但值的长度不能超过1GB
    key: 长度10到20
    value: 不要超过2k
    
    2、字符串对数字的加减
    6379> set id 1                                          #设置key是id,值是1
    6379> get id                                            #查看key
    6379> incr id                                           #自增1
    6379> incrby id 5                                       #自增指定数    
    6379> decr id                                           #自减1
    6379> decrby id 5                                       #自减指定数   
    
    3、其他操作
    6379> getset user01 wangwu                              #设置新数据并返回旧数据
    6379> get user01                                        #查看key的值
    6379> mset name zhangsan age 44                         #设置多个key
    6379> mget name age                                     #查看多个key的值
    6379> append  images .jpg                               #追加字符串
    6379> strlen  images                                    #计算字符串长度
    6379> substr  images 0 6                                #取0到6的值
    6379> help set                                          #查看单个命令帮助
    6379> help @string                                      #查看字符串所有命令的帮助

     2、List(列表)

    list是简单的字符串列表,按照插入顺序排序,可实现聊天系统和消息的队列
    6379> help @list                                        #列表帮助
    6379> lpush   students "zhang3"                         #插入元素到列表的最左边
    6379> lrange  students 0 1                              #查看列表0到1元素的值
    6379> rpush   students "wang5"                          #将插入元素到列表的最右边
    6379> llen    students                                  #查看列表元素的个数
    6379> lpop    students                                  #移除最左边的元素值
    6379> rpop    students                                  #移除最右边的元素值
    6379> lrem    students 2 "zhangsan"                     #删除两次指定的元素(从左向右删)
    6379> lrem    students 1 "zhangsan"                     #删除一次指定的元素
    6379> lrem    students 0 "zhangsan"                     #清空所有指定的元素
    6379> linsert students before b xxxx                    #在元素b的前边插入新元素
    6379> linsert students after b xxxx                     #在元素b的后边插入新元素

    3、集合(Sets)类型

    1、Set(无序集合)
    集合通过哈希表实现的,集合内的元素具有唯一性
    6379> help @set                                         #无序集合帮助
    6379> sadd users laoda                                  #添加一个元素
    6379> sadd users laoer laosan                           #添加两个元素
    6379> smembers  users                                   #查看集合里的所有元素(集合里的元素是无序的)
    6379> sismember users laoda                             #查看元素是否在集合中
    
    2、zset(有序集合)
    6379> help @sorted_set                                  #有序集合帮助
    6379> ZADD days 0 mon                                   #days:有序集合名,0:序号,mon:值
    6379> zrange days 0 6                                   #查看集合0到6元素的值(正序)
    6379> zrevrange days 0 -1                               #查看集合所有元素的值(倒序)
    6379> zscore days mon                                   #查看集合里值的排序
    6379> zrangebyscore days -inf 8                         #查看负无穷到5之间元素的值(区间查询)
    6379> zremrangebyscore days 1 7                         #删除1到7之间的元素(删除之间的元素) 

    4、Hash类型

    哈希可存储多个属性的数据(如user,name passwd)
    6379> hset k1 name zhang3 age 23                        #k1:哈希名,name:属性1,age:属性1
    6379> hvals k1                                          #查看所有属性
    6379> hgetall k1                                        #查看所有属性和值

    五、redis多实例

     1、创建多实例目录和配置文件

    1、创建redis多实例目录
    # mkdir -p /data/redis/638{0..1}/{conf,logs,pid}
    
    2、创建redis多实例配置文件
    # cp redis.conf /data/6380/conf/redis_6380.conf   
    # cp redis.conf /data/6381/conf/redis_6381.conf 
    # vim  redis_6380.conf 
      bind 10.0.0.135
      port 6380
      daemonize yes
      dir /data/redis/6380/     
      pidfile /data/6380/redis_6380.pid
      logfile /data/6380/logs/redis_6380.log
      dbfilename redis_6380.rdb
      appendonly yes
      appendfilename redis.aof
    # sed -i 's#6380#6381#g' /data/6381/conf/redis_6381.conf  

    2、启动redis多实例

    1、启动
    # redis-server /data/redis/6380/conf/redis_6380.conf
    # redis-server /data/redis/6381/conf/redis_6381.conf
    
    2、查看端口和进程
    # netstat -antup | grep redis
    # ps -ef | grep redis

     六、 Redis主从同步

    1、Redis主从同步特点

    1、一个master可以拥有多个slave
    2、多个slave可以连接同一个master,还可以连接到其他slave
    3、主从复制不会阻塞master,在同步数据时,master可以继续处理客户端的请求
    4、提高系统的伸缩性

    2、Redis主从同步的过程

    1、Slave连接到Master服务器
    2、Slave发送SYNC命令
    3、Master备份数据到rdb文件
    4、Master把rdb文件传输给Slave
    5、Slave把rdb文件导入到数据库中

    3、Redis的主从同步的应用

    1、一个master可有多个slave,一个slave还可以有多个slave
    2、主从同步不会阻塞master,但是会阻塞slave(初次同步数据,会阻塞客户端的请求)
    3、主从同步提高系统的伸缩,用多个slave处理客户端的读请求
    4)master不做持久化,在slave上做,可提高集群的性能,也可在slave上做数据的备份
    5)对于老版本的redis,每次重连都会重新发送所有数据

    4、配置主从同步

    1、方法1(临时生效)
    
    # redis-cli slaveof 10.0.0.135 6380                     #启动主从同步
    # redis-cli slaveof no one                              #停止主从同步
    
    2、方法2(永久生效)
    # vim redis_6381.conf  
      slaveof 10.0.0.135 6380                               #主库的IP和端口
      masterauth 123456                                     #主库的密码

    5、同步过程

    * Connecting to MASTER 192.168.0.135:6379                      #连接master
    * MASTER <-> SLAVE sync started                                #开始发送sync
    * Non blocking connect for SYNC fired the event.               #这是一个不阻塞事件
    * Master replied to PING, replication can continue...          #master应答了ping,同步开始
    * Partial resynchronization not possible (no cached master)    #部分重新同步不可能(master无缓存内容)
    * Full resync from master:                                     #从master同步全部数据 
    * MASTER <-> SLAVE sync: receiving 49 bytes from master        #从master接收到49字节数据
    * MASTER <-> SLAVE sync: Flushing old data                     #刷新旧数据
    * MASTER <-> SLAVE sync: Loading DB in memory                  #数据放到内存
    * MASTER <-> SLAVE sync: Finished with success                 #同步完成
    * Background append only file rewriting started by pid 3620    #AOF重写
    * Background AOF rewrite terminated with success               #AOF重写成功
    * Background AOF rewrite finished successfully                 #AOF重写完毕
      

    6、主从相关参数

    1、主从同步测试
    # redis-cli -a 123456 -p 6381 monitor                   #监听主服务写入操作
    # redis-cli -a 123456 -p 6380 get name                  #查看key
    # redis-cli -a 123456 -p 6380 set name tom              #设置一个key和value
    
    2、主从同步相关参数
    slave-serve-stale-data yes                              #yes:从不能连接主,从可正常提供服务,数据是旧的,no:不提供服务,返回错误信息
    slave-read-only yes                                     #设置从库只读模式
    repl-ping-slave-period 10                               #每10秒发送ping到master
    repl-backlog-size 1mb                                   #backlog大小(主通过backlog实现从的增量同步)
    repl-backlog-ttl 3600                                   #主从断开时,backlog的生存周期   
    slave-priority 100                                      #slave的优先级
    
    3、查看redis各项参数的方法
    6379> info                                              #查看所有的信息
    6379> info cpu                                          #查看CPU的信息
    6379> info clients                                      #查看客户端信息
    6379> info replication                                  #查看同步信息
      role:master                                           #角色是主
      connected_slaves:1                                    #连接从的数量
      slave0:ip="",port="",state=online,offset=11972,lag=1  #从库ip,端口,状态,偏移量等

    七、redis的高级特性

    1、redis的订阅功能

    1、介绍
    pub(发布)/sub(订阅)是一种消息通信模式,主要目的解耦发布者和订阅者之间的耦合
    redis可将数据推到消息队列中,其它人可通过队列获取消息
    
    2、开启的订阅功能
    6379> subscribe first                                   #开启并订阅频道(一个窗口)
    6379> subscribe first second                            #可订阅多个频道
    
    3、对频道推送                             
    6379> publish first 'welcome'                           #向频道推送
    6379> (integer) 2                                       #推送成功的人数(只要推送端推送,订阅端就能看到)
    6379> help @pubsub                                      #更多获取帮助

    2、redis数据过期设置及过期机制

    1、过期机制
    1) 定时删除
    设置key的过期时间的同时,创建一个定时器,到期时触发,对key删除
    2) 惰性删除
    key过期不删除,每次访问时检查是否过期,若过期,则删除key,并返回空(null)
    3) 定期删除
    每隔一段时间,检查有过期时间的key,删除已过期的key
    
    2、过期设置
    6379> expire name 5                                     #设置key5秒后过期
    6379> TTL name                                          #查看key过期时间(-1:永不过期,-2:已过期)
    6379> get name                                          #过期后的key,无法获取value的
    6379> help @generic 

    3、事务性

    1、组合型的命令
    redis支持简单的组合型的命令,例如以nx结尾的命令,key不存在时,为key设置指定的值
    6379> exists name                                       #查询key是否存在  
    6379> setnx name tom                                    #当key不存在时,设置key的值
    6379> setnx name zhang3                                 #当key存在时,不执行任何操作
    6379> get name                                          #没有被覆盖
    
    2、事务
    6379> set name tom                                      #设置一个key
    6379> get name                                          #查看key的值
    6379> multi                                             #开始一个事务
    6379> set name a                                        #当事务中有错误时,将都不执行
    6379> set name b                                        
    6379> exec                                              #提交事务(discard:取消事务)

     4、redis持久化

    1、快照(Snapshotting)
    1) 介绍
    将内存中数据,以快照的方式写入到文件中,redis宕机会丢失最后一次快照的数据
    2) 配置
    方法一
    # vim redis.conf
      dir /data/redis/                                      #rdb存储的路径
      dbfilename dump.rdb                                   #rdb文件名
      save 900 1                                            #900秒内1个key被修改,触发快照
      save 300 10                                           #300秒内10个key被修改,触发快照
      save 60  10000                                        60秒内10000个key被修改,触发快照
      rdbcompression no                                     #关闭rdb压缩,影响cpu
      save ""                                               #关闭rdb
    方法二
    6379> redis-cli config set save "180 1 120 10 60 10000" #开启rdb
    6379> redis-cli config rewrite                          #配置保存到文件    
    6379> redis-cli config set save ""                      #关闭rdb
    3) 快照原理
    ① redis调用fork,产生一个子进程
    ② 父进程处理client请求,子进程将内存内容写入到临时文件,由于Linux的写时复制机制,子进程的数据是fork时的一个快照
    ③ 当子进程将快照写入临时文件后,把临时文件替换快照文件,然后子进程退出
    4) 命令快照
    save: 主线程保存快照,会阻塞所有client请求(不推荐)
    bgsave: 开启一个子进程保存快照,不会阻塞客户端请求(推荐)
    5) 其他
    每次快照都是将内存数据完整写入到磁盘,如果数据量大,写操作多,会引起大量的磁盘io,严重影响性能
    redis关闭时,会自动后台保存并退出,启动时,会读取RDB文件,若找不到RDB文件,则认为数据丢失
    
    2、aof(日志方式)
    1) 介绍
    redis将收到的写操作,通过write函数追加到文件中,类似MySQL的binlog日志方式
    2) 配置
    # vim redis.conf
      appendonly yes                                            #启用aof
    3) aof文件更新策略
      appendfsync always                                        #收到写命令就立即写入磁盘,最慢,但数据不会丢失
      appendfsync everysec                                      #默认方式,每秒写入磁盘一次,会丢失前1秒的数据
      appendfsync no                                            #完全依赖os,性能最好,数据会丢失
    4) aof文件的自动重写
      auto-aof-rewrite-percentage 100                           #当aof文件增长比例100%时,触发自动重写
      auto-aof-rewrite-min-size 64mb                            #当aof文件大小到64m,触发自动重写
    6379> bgrewriteaof                                          #手动触发自动重写
    5) aof保存过程
    ① redis调用fork,产生一个子进程
    ② 子进程会根据内存中的快照,往临时文件中写人数据变化的命令
    ③ 父进程处理client请求,并把收到的写操作缓存
    ④ 当子进程把快照内容写完后,发信号通知父进程,父进程把缓存的写命令,写入到临时文件中
    ⑤ 父进程用临时文件,替换老的aof文件,并重命名,后面收到的写命令,往新的aof文件中追加
    备注: 重写aof文件,并没有读取旧的aof文件,而是重写一个新的aof文件,当redis启动会加载aof文件,用命令重建整个数据库

    八、redis的优化

    1、常用命令
    6379> flushdb                                           #清空当前库的数据
    6379> flushall                                          #清空所有库的数据
    6379> config get *                                      #查看当前配置信息
    6379> config set appendonly yes                         #在线修改
    # redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 10000  #100个并发,一万次请求
    
    2、系统参数优化
    1) 系统文件描述符
    # echo "* - nofile 10240" >> /etc/security/limits.conf 
    # bash && ulimit -n 
    2) TCP连接数
    # echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf
    # sysctl -p
    3) 系统内存分配策略
    # echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf 
    # sysctl -p
    4) 关闭系统大页内存
    # echo never > /sys/kernel/mm/transparent_hugepage/enabled 
    # echo never > /sys/kernel/mm/transparent_hugepage/defrag 
    
    3、内存清理算法
    volatile-lru                                            #LRU算法删除过期的key
    volatile-random                                         #随机删除过期的key
    volatile-ttl                                            #删除即将过期的key
    allkeys-lru                                             #LRU算法删除所有key
    allkeys-random                                          #随机删除所有key
    noeviction                                              #不删除key,只返回错误
    6379> config get maxmemory-policy                   #查看内存清理算法
    6379> config get maxmemory-policy volatile-lru          #设置内存清理算法
    
    4、内存优化
    hash-max-zipmap-entries 64                              #hash的最大元素数,当超过时,采用特殊hash算法
    hash-max-zipmap-value 512                               #hash的最大元素值,当超过时,采用特殊hash算法
    list-max-ziplist-value 64                               #列表的最大元素值,当超过时,采用压缩列表
    list-max-ziplist-entries 512                            #列表的最大元素数,当超过时,采用压缩列表
    set-max-intset-entries 512                              #限制集合中member个数,超出则不采取intset存储
    activerehashing yes                                     #是否激活重置哈希
    
    5、redis优化总结
    ① 根据业务需要,选择合适的数据类型,并为不同的应用场景,设置相应的紧凑存储参数
    ② 当业务场景不需要数据持久化时,关闭持久化,可获得最佳的性能和最大的内存使用量
    ③ 若使用持久化,根据是否容忍丢失部分数据,选择持久化方式,不要用虚拟内存vm及disk store方式,每秒实时写入AOF文件
    ④ 尽量不要让redis的内存,超过总内存的60%
    ⑤ 设置参数maxmemory,限制redis不会过多,使用物理内存而导致swap,设置参数vm-enabled no(不用虚拟内存)
    ⑥ 大数据量尽量按业务,用多个redis instance把数据分散开
    
    
    6、批量插入数据
    for i in `seq -w 50`;do redis-cli set name_$i value_$i;done

    九、redis的状态信息

    1、服务器的信息
    # Server                             
    redis_version:4.0.10                                #redis服务器版本
    redis_mode:standalone                               #运行模式(单机或集群) 
    multiplexing_api:epoll                              #使用的事件处理模型
    uptime_in_days:0                                    #服务器启动总时间,单位是天
    hz:10                                               #redis内部调度(关闭timeout客户端,删除过期key)
    lru_clock:8197344                                   #自增时间,用于LRU管理
           
    2、客户端信息    
    # Clients      
    connected_clients:1                                 #当前客户端连接数(不包括slave的连接)
    blocked_clients:0                                   #被阻塞的客户端数
           
    3、内存信息
    # Memory                          
    used_memory:2995728                                 #已用的内存,单位为字节(byte)
    used_memory_human:2.86M                             #易读方式显示
    used_memory_rss:4636672                             #系统给redis分配的内存(和top、ps显示的一致)
    used_memory_rss_human:4.42M                         #易读方式显示
    used_memory_peak:15517016                           #内存使用的峰值大小
    used_memory_peak_human:14.80M                       #易读方式显示
    used_memory_peak_perc:19.31%                        #峰值内存超出分配内存(used_memory)的百分比
    used_memory_startup:786608                          #Redis启动时的初始内存
    total_system_memory:2229866496                      #系统内存总量
    total_system_memory_human:2.08G                     #易读方式显示
    used_memory_lua:37888                               #lua引擎使用的内存
    used_memory_lua_human:37.00K                        #易读方式显示
    maxmemory:0                                         #最大内存(0不限制)
    maxmemory_human:0B                                  #易读方式显示
    mem_fragmentation_ratio:1.55                        #内存碎片率(used_memory_rss和used_memory的比率,小于1:使用swap,大于1:碎片多,增删操作增加碎片)
    mem_allocator:jemalloc-4.0.3                        #内存分配器
    
    4、持久化信息
    # Persistence                                   
    loading:0                                           #是否正在加载持久化文件
    rdb_changes_since_last_save:0                       #自上次rdb后,数据的改动
    rdb_bgsave_in_progress:0                            #bgsave是否操作
    rdb_last_save_time:1534918159                       #上次bgsave的时间戳
    rdb_last_bgsave_status:ok                           #上次bgsave的状态
    rdb_last_bgsave_time_sec:0                          #上次bgsave的使用的时间
    rdb_current_bgsave_time_sec:-1                      #当前bgsave已耗费的时间(如果有)
    rdb_last_cow_size:438272                            #上次rbd写时复制分配的字节大小
    aof_enabled:1                                       #是否开启AOF
    aof_rewrite_in_progress:0                       #AOF是否正在自动重写(rewrite)
    aof_rewrite_scheduled:0                             #是否要在rdb的bgsave结束后执行rewrite
    aof_last_rewrite_time_sec:1                         #上次rewrite使用的时间(单位s)
    aof_current_rewrite_time_sec:-1                     #当前rewrite已耗费的时间(如果有)
    aof_last_bgrewrite_status:ok                        #上次bgrewrite的状态
    aof_last_write_status:ok                            #上次AOF文件写入状态
    aof_last_cow_size:581632                            #上次重写写时复制分配的字节大小
    aof_current_size:2634673                            #AOF当前大小
    aof_base_size:2473591                               #AOF上次启动或rewrite的大小
    aof_pending_rewrite:0                               #同上面的aof_rewrite_scheduled
    aof_buffer_length:0                                 #AOF buffer的大小
    aof_rewrite_buffer_length:0                         #AOF rewrite buffer的大小
    aof_pending_bio_fsync:0                             #后台IO队列中等待fsync执行的个数
    aof_delayed_fsync:0                                 #被延迟fsync调用数量
      
    5、统计信息
    # Stats                          
    total_connections_received:220209                   #连接过的客户端总数
    total_commands_processed:447805                     #执行过的命令总数
    instantaneous_ops_per_sec:0                         #每秒处理命令数
    total_net_input_bytes:13682780                      #输入网络流量总数
    total_net_output_bytes:10737650                     #输出网络流量总数
    instantaneous_input_kbps:0.02                       #网络读取速率
    instantaneous_output_kbps:0.00                      #网络写入速率
    rejected_connections:0                              #拒绝的连接个数(已达到maxclients限制)
    sync_full:1                                         #主从完全同步成功次数
    sync_partial_ok:0                                   #主从部分同步成功次数
    sync_partial_err:1                                  #主从部分同步失败次数
    expired_keys:0                                      #过期key的数量
    evicted_keys:0                                      #剔除(超过maxmemory)的key的数量
    keyspace_hits:0                                     #命中key次数
    keyspace_misses:0                                   #没命中key次数
    pubsub_channels:0                                   #当前使用中的频道数量
    pubsub_patterns:0                                   #当前使用中的模式数量
    latest_fork_usec:401                                #上次fork消耗的时间
    
    6、主从信息
    # Replication                
    role:master                                         #角色(主从)
    connected_slaves:1                                  #连接的从库数量
    slave0:ip="",port="",state=online,offset=123,lag=0  #从库信息
    master_replid:2757c33a                              #复制ID
    master_replid2:0000000                              #第二个复制ID(用于failover的PSYNC)
    master_repl_offset:7672755                          #主从同步偏移量
    repl_backlog_active:1                               #复制缓冲区的状态
    repl_backlog_size:1048576                           #复制缓冲区的大小
    repl_backlog_first_byte_offset:6624180              #复制缓冲区的主偏移量
    repl_backlog_histlen:1048576                        #复制缓冲区数据的大小
    
    7、cpu信息
    # CPU
    used_cpu_sys:23.63                                  #主进程内核态消耗cpu的时间
    used_cpu_user:13.16                                 #主进程用户态消耗cpu的时间
    used_cpu_sys_children:0.31                          #子进程内核态消耗cpu的时间
    used_cpu_user_children:0.14                         #子进程用户态消耗cpu的时间
    
    8、集群信息
    # Cluster              
    cluster_enabled:0                                   #集群未开启
    
    9、数据库的键值信息
    # Keyspace           
    db0:keys=1,expires=0,avg_ttl=0                      #key总数,带有过期时间的key的总数,平均存活时间

     十、redis的高可用(哨兵+vip)

    1、环境

                redis-server             sentinel(哨兵)
    主节点     192.168.1.11:8000       192.168.1.11:7000
    从节点     192.168.1.12:8000       192.168.1.12:7000
    从节点     192.168.1.13:8000       192.168.1.13:7000

    2、配置主从复制(sentinel基于主从)

    1、创建master配置文件(主节点)
    # vim redis.conf
      port 8000            
      daemonize yes         
      bind 0.0.0.0          
      pidfile /var/run/redis-8000.pid    
      logfile /var/log/redis/redis-8000.log    
      requirepass 123456
    
    2、创建slave配置文件(2个从节点)
    # vim redis.conf
      port 8000
      daemonize yes
      bind 0.0.0.0
      pidfile /var/run/redis-8000.pid
      logfile /var/log/redis/redis-8000.log
      slaveof 192.168.1.11 8000      
      masterauth 123456        
    
    3、启动redis(所有节点)
    # redis-server  redis.conf

    3、安装部署redis-sentinel(所有节点)

    1、创建sentinel配置文件
    # vim sentinel.conf
      port 7000                    
      sentinel monitor mymaster 192.168.1.11 8000 2         #监控,别名,主库ip和端口,投票数2
      sentinel down-after-milliseconds mymaster 5000        #主库宕机5秒,切库
      sentinel parallel-syncs mymaster 1                    #切库后,向主库同步数据的个数,1:轮询,2:并发
      sentinel failover-timeout mymaster 15000              #故障转移的超时时间
      sentinel auth-pass mymaster 123456                    #主库密码
    
    2、启动sentinel
    # redis-sentinel sentinel.conf
    
    3、查看sentinel信息
    # redis-cli -h 192.168.1.11 -p 7000 info sentinel 

    4、部署redis-sentinel的VIP

    1、修改配置文件(所有节点)
    # vim sentinel.conf
      port 7000                    
      sentinel monitor mymaster 192.168.1.11 8000 2         
      sentinel down-after-milliseconds mymaster 5000       
      sentinel parallel-syncs mymaster 1                    
      sentinel failover-timeout mymaster 15000              
      sentinel auth-pass mymaster 123456                   
      sentinel client-reconfig-script mymaster /data/redis/redis_vip.sh
    
    2、编写vip脚本(所有节点)
      sentinel在failover的时会执行client-reconfig-script脚本,
      并传递6个参数(<master-name>,<role>,<state>,<from-ip>,<from-port>,<to-ip>,<to-port>)
    # vim /data/redis/redis_vip.sh
      #!/bin/bash
      MASTER_IP=$6                                          #传第六个参数(新master的IP==<to-ip>)
      LOCAL_IP="192.168.1.12"                               #本地IP
      VIP="192.168.1.20"                                    #VIP
      NETMASK="24"              
      INTERFACE="eth0"             
      if [[ "${MASTER_IP}" == "${LOCAL_IP}" ]];then
          /usr/sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE}
              /usr/sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE}
              exit 0
      else
              /usr/sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE}
          exit 0
      fi
      exit 1
    # chmod +x /data/redis/redis_vip.sh
    
    3、重启服务(所有节点)
    # redis-cli -h 192.168.1.11 -p 7000 shutdown
    # redis-sentinel sentinel.conf
    # ip addr add 192.168.1.20/24 dev eth0                  #第一次时手动给master添加VIP
    # arping -q -c 3 -A 192.168.1.20 -I eth0                #让ip地址即刻生效

     十一、Redis Cluster集群

    1、介绍

    Redis集群使用数据分片来实现,一个集群有16384个哈希槽,支持主从自动切换,无中心化,不支持多库,只有一个db0

    2、环境(3节点)

    主节点     db01: 10.0.0.11:7000    db02: 10.0.0.12:7000    db03: 10.0.0.13:7000
    从节点     db02: 10.0.0.12:8000    db03: 10.0.0.13:8000    db01: 10.0.0.11:8000

    3、redis部署和调优

    1、安装redis
    # yum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake
    # tar xf redis-4.0.10.tar.gz -C /usr/src/
    # cd /usr/src/redis-4.0.10/
    # make
    # make MALLOC=jemalloc
    # make PREFIX=/usr/local/redis install
    
    2、系统调优 # echo "* - nofile 10240" >> /etc/security/limits.conf # echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf # echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf # sysctl -p # echo never > /sys/kernel/mm/transparent_hugepage/enabled # echo never > /sys/kernel/mm/transparent_hugepage/defrag # echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local # echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local

    4、安装部署redis集群

    1、创建目录(所有节点)
    # mkdir -p /data/redis-cluster/{7000,8000}
    2、创建配置文件(所有节点) ① master配置文件 # vim /data/redis-cluster/7000/redis_7000.conf bind 0.0.0.0 protected-mode yes port 7000 tcp-backlog 1024 timeout 0 tcp-keepalive 0 daemonize yes supervised no pidfile /data/redis-cluster/7000/redis_7000.pid loglevel notice logfile /data/redis-cluster/7000/redis_7000.log databases 16 always-show-logo yes save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename redis_7000.rdb dir /data/redis-cluster/7000/ slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no slave-lazy-flush no appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble no lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes cluster-enabled yes #开启集群模式 cluster-config-file nodes_7000.conf #集群node配置文件(动态更新) cluster-node-timeout 5000 #集群的超时时间 ② slave配置文件 # cp redis_7000.conf /data/redis-cluster/8000/redis_8000.conf # sed -i 's#7000#8000#g' redis_8000.conf 3、启动集群(所有节点) # redis-server /data/redis-cluster/7000/redis_7000.conf # redis-server /data/redis-cluster/8000/redis_8000.conf

    5、使用工具自动部署集群

    1、安装ruby环境(编译安装高版本ruby,版本大于2.2)
    # wget --no-check-certificate 'https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.7.tar.gz'
    # tar xf ruby-2.2.7.tar.gz -C /usr/src/
    # cd /usr/src/ruby-2.2.7/
    # ./configure && make && make install
    # ruby --version                        
    
    2、在线安装ruby的redis扩展 # gem install redis #版本要和redis差不多,大版本号一直 # gem install redis -v 3.3.5 #可指定版本安装
    3、使用工具部署集群(master上操作) # redis-trib.rb create 10.0.0.11:7000 10.0.0.12:7000 10.0.0.13:7000
    4、查看集群的信息 # redis-cli -p 7000 cluster nodes
    5、操作集群 # redis-cli -c -p 7000 set name zhang3 # redis-cli -c -p 7000 get name

    6、集群的重建(所有节点)

    1、删除cluster集群配置文件
    # rm -rf /data/redis-cluster/7000/nodes_7000.conf
    
    2、关闭集群
    # redis-cli -p 7000 shutdown
    
    3、启动集群
    # redis-server /data/redis-cluster/7000/redis_7000.conf
    
    4、重新创建redis-cluster集群
    # redis-trib.rb create 10.0.0.11:7000 10.0.0.12:7000 10.0.0.13:7000
    
    5、查看进程
    # ps -ef | grep cluster | grep -v grep

    7、集群添加从库

    # redis-trib.rb add-node --slave 10.0.0.12:8000 10.0.0.11:7000  #添加从8000,主7000
    # redis-trib.rb add-node --slave 10.0.0.13:8000 10.0.0.12:7000
    # redis-trib.rb add-node --slave 10.0.0.11:8000 10.0.0.13:7000
    # redis-cli -p 7000 cluster nodes                               #查看集群所有节点的信息

    8、其他

    1、集群的主从自动切换
    # redis-cli -p 7000 shutdown                                    #手动宕掉主
    # redis-cli -p 8000 cluster nodes                               #查看状态(从库变新主库)
    # redis-server /data/redis-cluster/7000/redis_7000.conf         #启动主
    # redis-cli -p 8000 cluster nodes                               #查看状态(主库变新从库)
    # redis-cli -p 7000 cluster failover                            #手动切换主从(主从角色切换)
    # redis-cli -p 8000 cluster nodes                               #查看状态(新从库变旧主库)
    
    2、Python操作集群
    # yum install python2-pip
    # pip install redis-py-cluster
    # vim redis_cluster.py 
      # -*- coding:utf-8 -*-
      from rediscluster import StrictRedisCluster
      redis_nodes = [
              {'host':'10.0.0.11','port':7000},
              {'host':'10.0.0.12','port':7000},
              {'host':'10.0.0.13','port':7000},
              {'host':'10.0.0.11','port':8000},
              {'host':'10.0.0.12','port':8000},
              {'host':'10.0.0.13','port':8000}
              ]
      redis_conn = StrictRedisCluster(startup_nodes=redis_nodes)
      redis_conn.set('key_test','values_test')
      print(redis_conn.get('key_test'))
    # python redis_cluster.py                                       #执行Python脚本        
    # redis-cli -c -p 7000 get key_test                             #查看key
    备注: 若其中一个节点挂了,不影响使用
    
    3、分析Redis的所有key和key的大小
    # pip install rdbtools                                  #pip安装rdbtools分析工具
    # rdb -c memory redis_7000.rdb > /tmp/rdb.csv
    # cat /tmp/rdb.csv | head
  • 相关阅读:
    [Spring cloud 一步步实现广告系统] 5. 投放系统配置+启动+实体类
    [Spring cloud 一步步实现广告系统] 4. 通用代码模块设计
    [Spring cloud 一步步实现广告系统] 3. 网关路由
    [Spring cloud 一步步实现广告系统] 1. 业务架构分析
    [Spring cloud 一步步实现广告系统] 2. 配置&Eureka服务
    [Java 开发利器Lombok] 常用注解演示
    使用maven快速入门
    [Spring-Cloud-Alibaba] Sentinel 规则持久化
    Java 类加载之匿名类和主类相互依赖问题
    [Spring-Cloud-Alibaba] Sentinel 整合RestTemplate & Feign
  • 原文地址:https://www.cnblogs.com/wuhg/p/10083553.html
Copyright © 2011-2022 走看看