zoukankan      html  css  js  c++  java
  • DAY 105 redis集群搭建

    1 redis介绍和基本安装
    -celery+redis:消息存储,队列
       -去重,计数,缓存,geo,
       -性能很高
       -源码安装
       
    2 api
    -公共api
       -字符串
       -列表
       -hash
       -集合
       -有序集合
       
    3 客户端
    -python 的客户端:redis模块
       
    4 高级使用
    -慢查询
       -pipline,事务
       -发布订阅
       -bitmap
       -HyperLogLog
       -geo
    5 持久化
    -rdb:快照方式
       -aof:日志方式
       
    6 主从复制
    -一主一从
       -一主多从
       
    7 哨兵(高可用)

     

    1 redis集群搭建

    # 第一种:最原始,一步步做(基本不用)
    -启动多个节点(6个节点)
       -相互meet
       -指派槽
       -做主从
    # 第二种:ruby脚本

    # 第三种:新版本上,官方直接支持用命令实现
    -redis-cli --cluster(meet,分配槽,做主从)
       
       
    # 第三种:
    ###1 生成6个配置文件起6个节点,6个配置文件
    port 7000
    daemonize yes
    dir "/opt/soft/redis/data/"
    logfile "7000.log"
    dbfilename "dump-7000.rdb"
    cluster-enabled yes
    cluster-config-file nodes-7000.conf
    cluster-require-full-coverage yes

    sed 's/7000/7001/g' redis-7000.conf > redis-7001.conf
    sed 's/7000/7002/g' redis-7000.conf > redis-7002.conf
    sed 's/7000/7003/g' redis-7000.conf > redis-7003.conf
    sed 's/7000/7004/g' redis-7000.conf > redis-7004.conf
    sed 's/7000/7005/g' redis-7000.conf > redis-7005.conf


    ###2 启动6个节点
    ./src/redis-server ./redis-7000.conf
    ./src/redis-server ./redis-7001.conf
    ./src/redis-server ./redis-7002.conf
    ./src/redis-server ./redis-7003.conf
    ./src/redis-server ./redis-7004.conf
    ./src/redis-server ./redis-7005.conf

    ps -ef |grep redis
    # 现在往任意一个节点中写数据,都写不进去

    ###3 meet,分配槽,建立主从

    ##./src/redis-cli --cluster help 查看cluster命令的使用
    redis-cli --cluster create --cluster-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
                           
    yes

    # 写入数据测试
    连接任意一个主节点:发现存需要去固定的节点存取
    所以我们使用(自动重定向到固定节点存取)
    ./src/redis-cli -a -p 7000

    1.1 扩容

    #配置文件
    sed 's/7000/7006/g' redis-7000.conf > redis-7006.conf
    sed 's/7000/7007/g' redis-7000.conf > redis-7007.conf

    #启动
    redis-server ./redis-7006.conf
    redis-server .redis-7007.conf

    # 让集群感知到新进来的
    redis-cli -p 7000 cluster meet 127.0.0.1 7006
    redis-cli -p 7000 cluster meet 127.0.0.1 7007

    #做主从
    redis-cli -p 7007 cluster replicate ca0a50decb2d75985599533471a1b49945db11dd

    # 迁移槽
    redis-cli --cluster reshard 127.0.0.1:7000
       -迁移多少
       -迁到谁(id)
       -all(均匀的从每个节点拿一些)
       -yes
       
    # 查看集群信息
    cluster nodes

    #测试

    缩容

    # 下线迁槽(把7006的1366个槽迁移到7000上)
    redis-cli --cluster reshard --cluster-from 7006的id --cluster-to 7000的id --cluster-slots 1366 127.0.0.1:7000
    yes

    redis-cli --cluster reshard --cluster-from 7006的id --cluster-to 7001的id --cluster-slots 1366 127.0.0.1:7001
    yes
    redis-cli --cluster reshard --cluster-from 7006的id --cluster-to 7002的id --cluster-slots 1365 127.0.0.1:7002
    yes

    # 忘记节点,关闭节点
    redis-cli --cluster del-node 127.0.0.1:7000 要下线的7007id  
    # 先下从,再下主,因为先下主会触发故障转移
    redis-cli --cluster del-node 127.0.0.1:7000 要下线的7006id


    # 关掉其中一个主,另一个从立马变成主顶上, 重启停止的主,发现变成了从

    2 缓存的优化和使用

    1 做缓存
    2 缓存更新策略
    -LRU -Least Recently Used,没有被使用时间最长的
    -LFU -Least Frequenty User,一定时间段内使用次数最少的
    -FIFO -First In First Out
       -LIRS (Low Inter-reference Recency Set)是一个页替换算法,相比于LRU(Least Recently Used)和很多其他的替换算法,LIRS具有较高的性能。这是通过使用两次访问同一页之间的距离(本距离指中间被访问了多少非重复块)作为一种尺度去动态地将访问页排序,从而去做一个替换的选择
       
       
    3 缓存穿透  缓存击穿 缓存雪崩
    ### 缓存穿透
    #描述:
    缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
    #解决方案:
    1 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
    2 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
    3 通过布隆过滤器实现,避免缓存穿透



    ### 缓存击穿
    #描述:
    缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
    #解决方案:
    设置热点数据永远不过期。


    ### 缓存雪崩
    #描述:
    缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,        缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
    # 解决方案:
    1 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
    2 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
    3 设置热点数据永远不过期。


    ##双写一致性
       1. 先更新数据库,再更新缓存
       2. 先删除缓存,再更新数据库
       3. 先更新数据库,再删除缓存(我们用的)

     

    3 mysql主从搭建

    1 写操作到主,读操作去从
    2 一台机器,使用docker搭建(配置文件)
    -

     

    4 django实现读写分离

    #1 基于docker
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    yum install docker-ce
    systemctl start docker  # 启动docker

    docker pull mysql:5.7   #拉取mysql5.7镜像
       
       
    # 2 修改配置文件
    ###主
    [mysqld]
    user=mysql
    character-set-server=utf8
    default_authentication_plugin=mysql_native_password
    secure_file_priv=/var/lib/mysql
    expire_logs_days=7
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    max_connections=1000

    server-id=100
    log-bin=mysql-bin


    ###从
    [mysqld]
    user=mysql
    character-set-server=utf8
    default_authentication_plugin=mysql_native_password
    secure_file_priv=/var/lib/mysql
    expire_logs_days=7
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    max_connections=1000

    server-id=101
    log-bin=mysql-slave-bin
    relay_log=edu-mysql-relay-bin


    ##3 启动容器,使用配置文件启动
    docker run  -di -v /home/mysql/data/:/var/lib/mysql -v /home/mysql/conf.d:/etc/mysql/conf.d -v /home/mysql/my.cnf:/etc/mysql/my.cnf -p 33307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
                       
                       
                       
    docker run  -di -v /home/mysql2/data/:/var/lib/mysql -v /home/mysql2/conf.d:/etc/mysql/conf.d -v /home/mysql2/my.cnf:/etc/mysql/my.cnf -p 33306:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

                       
    ##4 远程连接从库,新建一个用户(test)
    #连接主库
    mysql -h 47.100.50.84 -P 33307 -u root -p123456
    #在主库创建用户并授权
    ##创建test用户
    create user 'test'@'%' identified by '123';
    ##授权用户
    grant all privileges on *.* to 'test'@'%' ;
    ###刷新权限
    flush privileges;
    #查看主服务器状态(显示如下图)
    show master status;

     

    ### 5 从库的配置

    #连接从库
    mysql -h 47.100.50.84 -P 33306 -u root -p123456
    #配置详解
    /*
    change master to
    master_host='MySQL主服务器IP地址',
    master_user='之前在MySQL主服务器上面创建的用户名'
    master_password='之前创建的密码',
    master_log_file='MySQL主服务器状态中的二进制文件名',
    master_log_pos='MySQL主服务器状态中的position值';
    */
    #命令如下
    change master to master_host='47.100.50.84',master_port=33307,master_user='test',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=0;
    #启用从库
    start slave;
    #查看从库状态(如下图)
    show slave statusG;


    ### 6 测试主从
    #在主库上创建数据库test1,创建表,插入数据

     

    5 读写分离

    多数据库:
    python manage.py makemigraions

    python manage.py migrate app名称 --databse=配置文件数据名称的别名

    #手动操作:
       # 读(db1),写(default)分离
       res = models.Book.objects.all().using('db1')

       # 写到default中
       # models.Book.objects.using('default').create(name='西游记')

    #自动操作:
    ## 写一个py文件,新建一个类,如下
    class Router1:
       def db_for_read(self, model, **hints):

           return 'db1'

       def db_for_write(self, model, **hints):

           return 'default'
    ##在配置文件中配置
    DATABASE_ROUTERS = ['db_router.Router1',]
    ## 以后,自动的读写分离,不需要额外处理


    #粒度更细(指定读book表时,去db1库读)
    class Router1:
       def db_for_read(self, model, **hints):
           if model._meta.model_name == 'book':  # 通过表名限制更细粒度
               return 'db1'
           else:
               return 'default'

       def db_for_write(self, model, **hints):
           return 'default'

    补充

    1 你们项目的并发量
    -uwsgi+django  200以内
       -用户数:50w用户数
       -日活:1w
       -并发量:几百

     

  • 相关阅读:
    JS提取子字符串函数比较
    js事件定义方式和获取事件对象event总结
    让body的clientHeight与html的clientHeight相等的方法
    关于原型链和继承问题的思考:为什么不能直接把父类的prototype赋值给子类的prototype
    [javascript权威指南笔记02]Throw语句和异常处理机制try/catch/finally
    转载:javascript语句标签
    转:JS中强大的正则表达式
    分享我常用的Javascript工具函数
    对prototype,instanceof和constrctor的理解
    xml基础知识总结和回顾
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14914407.html
Copyright © 2011-2022 走看看