目前对于互联网公司不使用Redis的很少,Redis不仅仅可以作为key-value缓存,而且提供了丰富的数据结果如set、list、map等,可以实现很多复杂的功能;但是Redis本身主要用作内存缓存,不适合做持久化存储,因此目前有如SSDB、ARDB等,还有如京东的JIMDB,它们都支持Redis协议,可以支持Redis客户端直接访问;而这些持久化存储大多数使用了如LevelDB、RocksDB、LMDB持久化引擎来实现数据的持久化存储;京东的JIMDB主要分为两个版本:LevelDB和LMDB,而我们看到的京东商品详情页就是使用LMDB引擎作为存储的,可以实现海量KV存储;当然SSDB在京东内部也有些部门在使用;另外调研过得如豆瓣的beansDB也是很不错的。具体这些持久化引擎之间的区别可以自行查找资料学习。

Twemproxy是一个Redis/Memcached代理中间件,可以实现诸如分片逻辑、HashTag、减少连接数等功能;尤其在有大量应用服务器的场景下Twemproxy的角色就凸显了,能有效减少连接数。

Redis安装与使用

1、下载redis并安装

  1. cd /usr/servers/
  2. wget https://github.com/antirez/redis/archive/2.8.19.tar.gz
  3. tar -xvf 2.8.19.tar.gz
  4. cd redis-2.8.19/
  5. make

通过如上步骤构建完毕。

2、后台启动Redis服务器

  1. nohup /usr/servers/redis-2.8.19/src/redis-server  /usr/servers/redis-2.8.19/redis.conf &

3、查看是否启动成功

  1. ps -aux | grep redis

4、进入客户端

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 6379

5、执行如下命令

  1. 127.0.0.1:6379> set i 1
  2. OK
  3. 127.0.0.1:6379> get i
  4. "1"

通过如上命令可以看到我们的Redis安装成功。更多细节请参考http://redis.io/

SSDB安装与使用

1、下载SSDB并安装

  1. #首先确保安装了g++,如果没有安装,如ubuntu可以使用如下命令安装
  2. apt-get install g++
  3. cd /usr/servers
  4. wget https://github.com/ideawu/ssdb/archive/1.8.0.tar.gz
  5. tar -xvf 1.8.0.tar.gz
  6. make

2、后台启动SSDB服务器

  1. nohup /usr/servers/ssdb-1.8.0/ssdb-server  /usr/servers/ssdb-1.8.0/ssdb.conf &

3、查看是否启动成功

  1. ps -aux | grep ssdb

4、进入客户端

  1. /usr/servers/ssdb-1.8.0/tools/ssdb-cli -p 8888
  2. /usr/servers/redis-2.8.19/src/redis-cli  -p 888

因为SSDB支持Redis协议,所以用Redis客户端也可以访问

5、执行如下命令

  1. 127.0.0.1:8888> set i 1
  2. OK
  3. 127.0.0.1:8888> get i
  4. "1"

安装过程中遇到错误请参考http://ssdb.io/docs/zh_cn/install.html;对于SSDB的配置请参考官方文档https://github.com/ideawu/ssdb

Twemproxy安装与使用

首先需要安装autoconf、automake、libtool工具,比如ubuntu可以使用如下命令安装

  1. apt-get install autoconf automake
  2. apt-get install libtool

1、下载Twemproxy并安装

  1. cd /usr/servers
  2. wget https://github.com/twitter/twemproxy/archive/v0.4.0.tar.gz
  3. tar -xvf v0.4.0.tar.gz
  4. cd twemproxy-0.4.0/
  5. autoreconf -fvi
  6. ./configure && make

此处根据要注意,如上安装方式在有些服务器上可能在大量如mset时可能导致Twemproxy崩溃,需要使用如 CFLAGS="-O1" ./configure && make或CFLAGS="-O3 -fno-strict-aliasing" ./configure && make安装。

2、配置

  1. vim /usr/servers/twemproxy-0.4.0/conf/nutcracker.yml
  1. server1:
  2. listen: 127.0.0.1:1111
  3. hash: fnv1a_64
  4. distribution: ketama
  5. redis: true
  6. servers:
  7. - 127.0.0.1:6379:1

3、启动Twemproxy代理

  1. /usr/servers/twemproxy-0.4.0/src/nutcracker  -d -c /usr/servers/twemproxy-0.4.0/conf/nutcracker.yml

-d指定后台启动  -c指定配置文件;此处我们指定了代理端口为1111,其他配置的含义后续介绍。

4、查看是否启动成功

  1. ps -aux | grep nutcracker

5、进入客户端

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 1111

6、执行如下命令

  1. 127.0.0.1:1111> set i 1
  2. OK
  3. 127.0.0.1:1111> get i
  4. "1"

Twemproxy文档请参考https://github.com/twitter/twemproxy

到此基本的安装就完成了。接下来做一些介绍。

Redis设置

基本设置

  1. #端口设置,默认6379
  2. port 6379
  3. #日志文件,默认/dev/null
  4. logfile ""

Redis内存

  1. 内存大小对应关系
  2. # 1k => 1000 bytes
  3. # 1kb => 1024 bytes
  4. # 1m => 1000000 bytes
  5. # 1mb => 1024*1024 bytes
  6. # 1g => 1000000000 bytes
  7. # 1gb => 1024*1024*1024 bytes
  8. #设置Redis占用100mb的大小
  9. maxmemory  100mb
  10. #如果内存满了就需要按照如相应算法进行删除过期的/最老的
  11. #volatile-lru 根据LRU算法移除设置了过期的key
  12. #allkeys-lru  根据LRU算法移除任何key(包含那些未设置过期时间的key)
  13. #volatile-random/allkeys->random 使用随机算法而不是LRU进行删除
  14. #volatile-ttl 根据Time-To-Live移除即将过期的key
  15. #noeviction   永不过期,而是报错
  16. maxmemory-policy volatile-lru
  17. #Redis并不是真正的LRU/TTL,而是基于采样进行移除的,即如采样10个数据移除其中最老的/即将过期的
  18. maxmemory-samples 10

而如Memcached是真正的LRU,此处要根据实际情况设置缓存策略,如缓存用户数据时可能带上了过期时间,此时采用volatile-lru即可;而假设我们的数据未设置过期时间,此时可以考虑使用allkeys-lru/allkeys->random;假设我们的数据不允许从内存删除那就使用noeviction。

内存大小尽量在系统内存的60%~80%之间,因为如客户端、主从时复制时都需要缓存区的,这些也是耗费系统内存的。

Redis本身是单线程的,因此我们可以设置每个实例在6-8GB之间,通过启动更多的实例提高吞吐量。如128GB的我们可以开启8GB * 10个实例,充分利用多核CPU。

Redis主从

实际项目时,为了提高吞吐量,我们使用主从策略,即数据写到主Redis,读的时候从从Redis上读,这样可以通过挂载更多的从来提高吞吐量。而且可以通过主从机制,在叶子节点开启持久化方式防止数据丢失。

  1. #在配置文件中挂载主从,不推荐这种方式,我们实际应用时Redis可能是会宕机的
  2. slaveof masterIP masterPort
  3. #从是否只读,默认yes
  4. slave-read-only yes
  5. #当从失去与主的连接或者复制正在进行时,从是响应客户端(可能返回过期的数据)还是返回“SYNC with master in progress”错误,默认yes响应客户端
  6. slave-serve-stale-data yes
  7. #从库按照默认10s的周期向主库发送PING测试连通性
  8. repl-ping-slave-period 10
  9. #设置复制超时时间(SYNC期间批量I/O传输、PING的超时时间),确保此值大于repl-ping-slave-period
  10. #repl-timeout 60
  11. #当从断开与主的连接时的复制缓存区,仅当第一个从断开时创建一个,缓存区越大从断开的时间可以持续越长
  12. # repl-backlog-size 1mb
  13. #当从与主断开持续多久时清空复制缓存区,此时从就需要全量复制了,如果设置为0将永不清空
  14. # repl-backlog-ttl 3600
  15. #slave客户端缓存区,如果缓存区超过256mb将直接断开与从的连接,如果持续60秒超过64mb也会断开与从的连接
  16. client-output-buffer-limit slave 256mb 64mb 60

此处需要根据实际情况设置client-output-buffer-limit slave和 repl-backlog-size;比如如果网络环境不好,从与主经常断开,而每次设置的数据都特别大而且速度特别快(大量设置html片段)那么就需要加大repl-backlog-size。

主从示例

  1. cd /usr/servers/redis-2.8.19
  2. cp redis.conf redis_6660.conf
  3. cp redis.conf redis_6661.conf
  4. vim redis_6660.conf
  5. vim redis_6661.conf

将端口分别改为port 6660和port 6661,然后启动

  1. nohup /usr/servers/redis-2.8.19/src/redis-server  /usr/servers/redis-2.8.19/redis_6660.conf &
  2. nohup /usr/servers/redis-2.8.19/src/redis-server  /usr/servers/redis-2.8.19/redis_6661.conf &

查看是否启动

  1. ps -aux | grep redis

进入从客户端,挂主

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 6661
  1. 127.0.0.1:6661> slaveof 127.0.0.1 6660
  2. OK
  3. 127.0.0.1:6661> info replication
  4. # Replication
  5. role:slave
  6. master_host:127.0.0.1
  7. master_port:6660
  8. master_link_status:up
  9. master_last_io_seconds_ago:3
  10. master_sync_in_progress:0
  11. slave_repl_offset:57
  12. slave_priority:100
  13. slave_read_only:1
  14. connected_slaves:0
  15. master_repl_offset:0
  16. repl_backlog_active:0
  17. repl_backlog_size:1048576
  18. repl_backlog_first_byte_offset:0
  19. repl_backlog_histlen:0

进入主

  1. /usr/servers/redis-2.8.19# /usr/servers/redis-2.8.19/src/redis-cli  -p 6660
  1. 127.0.0.1:6660> info replication
  2. # Replication
  3. role:master
  4. connected_slaves:1
  5. slave0:ip=127.0.0.1,port=6661,state=online,offset=85,lag=1
  6. master_repl_offset:85
  7. repl_backlog_active:1
  8. repl_backlog_size:1048576
  9. repl_backlog_first_byte_offset:2
  10. repl_backlog_histlen:84
  11. 127.0.0.1:6660> set i 1
  12. OK

进入从

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 6661
  1. 127.0.0.1:6661> get i
  2. "1"

此时可以看到主从挂载成功,可以进行主从复制了。使用slaveof no one断开主从。

 

Redis持久化

Redis虽然不适合做持久化存储,但是为了防止数据丢失有时需要进行持久化存储,此时可以挂载一个从(叶子节点)只进行持久化存储工作,这样假设其他服务器挂了,我们可以通过这个节点进行数据恢复。

Redis持久化有RDB快照模式和AOF追加模式,根据自己需求进行选择。

RDB持久化

  1. #格式save seconds changes 即N秒变更N次则保存,从如下默认配置可以看到丢失数据的周期很长,通过save “” 配置可以完全禁用此持久化
  2. save 900 1
  3. save 300 10
  4. save 60 10000
  5. #RDB是否进行压缩,压缩耗CPU但是可以减少存储大小
  6. rdbcompression yes
  7. #RDB保存的位置,默认当前位置
  8. dir ./
  9. #RDB保存的数据库名称
  10. dbfilename dump.rdb
  11. #不使用AOF模式,即RDB模式
  12. appendonly no

可以通过set一个数据,然后很快的kill掉redis进程然后再启动会发现数据丢失了。

AOF持久化

AOF(append only file)即文件追加模式,即把每一个用户操作的命令保存下来,这样就会存在好多重复的命令导致恢复时间过长,那么可以通过相应的配置定期进行AOF重写来减少重复。

  1. #开启AOF
  2. appendonly yes
  3. #AOF保存的位置,默认当前位置
  4. dir ./
  5. #AOF保存的数据库名称
  6. appendfilename appendonly.aof
  7. #持久化策略,默认每秒fsync一次,也可以选择always即每次操作都进行持久化,或者no表示不进行持久化而是借助操作系统的同步将缓存区数据写到磁盘
  8. appendfsync everysec
  9. #AOF重写策略(同时满足如下两个策略进行重写)
  10. #当AOF文件大小占到初始文件大小的多少百分比时进行重写
  11. auto-aof-rewrite-percentage 100
  12. #触发重写的最小文件大小
  13. auto-aof-rewrite-min-size 64mb
  14. #为减少磁盘操作,暂缓重写阶段的磁盘同步
  15. no-appendfsync-on-rewrite no

此处的appendfsync everysec可以认为是RDB和AOF的一个折中方案。

#当bgsave出错时停止写(MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.),遇到该错误可以暂时改为no,当写成功后再改回yes

stop-writes-on-bgsave-error yes

更多Redis持久化请参考http://redis.readthedocs.org/en/latest/topic/persistence.html

Redis动态调整配置

获取maxmemory(10mb)

  1. 127.0.0.1:6660> config get maxmemory
  2. 1) "maxmemory"
  3. 2) "10485760"

设置新的maxmemory(20mb)

  1. 127.0.0.1:6660> config set maxmemory 20971520
  2. OK

但是此时重启redis后该配置会丢失,可以执行如下命令重写配置文件

  1. 127.0.0.1:6660> config rewrite
  2. OK

注意:此时所以配置包括主从配置都会重写。

 

Redis执行Lua脚本

Redis客户端支持解析和处理lua脚本,因为Redis的单线程机制,我们可以借助Lua脚本实现一些原子操作,如扣减库存/红包之类的。此处不建议使用EVAL直接发送lua脚本到客户端,因为其每次都会进行Lua脚本的解析,而是使用SCRIPT LOADEVALSHA进行操作。未来不知道是否会用luajit来代替lua,让redis lua脚本性能更强。

到此基本的Redis知识就讲完了。

Twemproxy设置

一旦涉及到一台物理机无法存储的情况就需要考虑使用分片机制将数据存储到多台服务器,可以说是Redis集群;如果客户端都是如Java没什么问题,但是如果有多种类型客户端(如PHP、C)等也要使用那么需要保证它们的分片逻辑是一样的;另外随着客户端的增加,连接数也会随之增多,发展到一定地步肯定会出现连接数不够用的;此时Twemproxy就可以上场了。主要作用:分片、减少连接数。另外还提供了Hash Tag机制来帮助我们将相似的数据存储到同一个分片。另外也可以参考豌豆荚的https://github.com/wandoulabs/codis

基本配置

其使用YML语法,如

  1. server1:
  2. listen: 127.0.0.1:1111
  3. hash: fnv1a_64
  4. distribution: ketama
  5. timeout:1000
  6. redis: true
  7. servers:
  8. - 127.0.0.1:6660:1
  9. - 127.0.0.1:6661:1

server1:是给当前分片配置起的名字,一个配置文件可以有多个分片配置;

listen : 监听的ip和端口;

hash:散列算法;

distribution:分片算法,比如一致性Hash/取模;

timeout:连接后端Redis或接收响应的超时时间;

redis:是否是redis代理,如果是false则是memcached代理;

servers:代理的服务器列表,该列表会使用distribution配置的分片算法进行分片;

分片算法

hash算法:

one_at_a_time

md5

crc16

crc32 (crc32 implementation compatible with libmemcached)

crc32a (correct crc32 implementation as per the spec)

fnv1_64

fnv1a_64

fnv1_32

fnv1a_32

hsieh

murmur

jenkins

分片算法:

ketama(一致性Hash算法)

modula(取模)

random(随机算法)

服务器列表

servers:

- ip:port:weight alias

servers:

- 127.0.0.1:6660:1

- 127.0.0.1:6661:1

或者

servers:

- 127.0.0.1:6660:1 server1

- 127.0.0.1:6661:1 server2

推荐使用后一种方式,默认情况下使用ip:port:weight进行散列并分片,这样假设服务器宕机换上新的服务器,那么此时得到的散列值就不一样了,因此建议给每个配置起一个别名来保证映射到自己想要的服务器。即如果不使用一致性Hash算法来作缓存服务器,而是作持久化存储服务器时就更有必要了(即不存在服务器下线的情况,即使服务器ip:port不一样但仍然要得到一样的分片结果)。

HashTag

比如一个商品有:商品基本信息(p:id:)、商品介绍(d:id:)、颜色尺码(c:id:)等,假设我们存储时不采用HashTag将会导致这些数据不会存储到一个分片,而是分散到多个分片,这样获取时将需要从多个分片获取数据进行合并,无法进行mget;那么如果有了HashTag,那么可以使用“::”中间的数据做分片逻辑,这样id一样的将会分到一个分片。

nutcracker.yml配置如下

  1. server1:
  2. listen: 127.0.0.1:1111
  3. hash: fnv1a_64
  4. distribution: ketama
  5. redis: true
  6. hash_tag: "::"
  7. servers:
  8. - 127.0.0.1:6660:1 server1
  9. - 127.0.0.1:6661:1 server2

连接Twemproxy

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 1111
  1. 127.0.0.1:1111> set p:12: 1
  2. OK
  3. 127.0.0.1:1111> set d:12: 1
  4. OK
  5. 127.0.0.1:1111> set c:12: 1
  6. OK

在我的服务器上可以连接6660端口

  1. /usr/servers/redis-2.8.19/src/redis-cli  -p 6660
  2. 127.0.0.1:6660> get p:12:
  3. "1"
  4. 127.0.0.1:6660> get d:12:
  5. "1"
  6. 127.0.0.1:6660> get c:12:
  7. "1"

一致性Hash与服务器宕机

如果我们把Redis服务器作为缓存服务器并使用一致性Hash进行分片,当有服务器宕机时需要自动从一致性Hash环上摘掉,或者其上线后自动加上,此时就需要如下配置:

#是否在节点故障无法响应时自动摘除该节点,如果作为存储需要设置为为false

auto_eject_hosts: true

#重试时间(毫秒),重新连接一个临时摘掉的故障节点的间隔,如果判断节点正常会自动加到一致性Hash环上

server_retry_timeout: 30000

#节点故障无法响应多少次从一致性Hash环临时摘掉它,默认是2

server_failure_limit: 2

支持的Redis命令

不是所有Redis命令都支持,请参考https://github.com/twitter/twemproxy/blob/master/notes/redis.md

因为我们所有的Twemproxy配置文件规则都是一样的,因此我们应该将其移到我们项目中。

  1. cp /usr/servers/twemproxy-0.4.0/conf/nutcracker.yml  /usr/example/

另外Twemproxy提供了启动/重启/停止脚本方便操作,但是需要修改配置文件位置为/usr/example/nutcracker.yml。

  1. chmod +x /usr/servers/twemproxy-0.4.0/scripts/nutcracker.init
  2. vim /usr/servers/twemproxy-0.4.0/scripts/nutcracker.init

将OPTIONS改为

OPTIONS="-d -c /usr/example/nutcracker.yml"

另外注释掉. /etc/rc.d/init.d/functions;将daemon --user ${USER} ${prog} $OPTIONS改为${prog} $OPTIONS;将killproc改为killall。

这样就可以使用如下脚本进行启动、重启、停止了。

/usr/servers/twemproxy-0.4.0/scripts/nutcracker.init {start|stop|status|restart|reload|condrestart}

对于扩容最简单的办法是:

1、创建新的集群;

2、双写两个集群;

3、把数据从老集群迁移到新集群(不存在才设置值,防止覆盖新的值);

4、复制速度要根据实际情况调整,不能影响老集群的性能;

5、切换到新集群即可,如果使用Twemproxy代理层的话,可以做到迁移对读的应用透明。

第三章 (Nginx+Lua)Redis/SSDB安装与使用的更多相关文章

  1. 【重要】Nginx模块Lua-Nginx-Module学习笔记(三)Nginx + Lua + Redis 已安装成功(非openresty 方式安装)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis 一. 目标 使用Redis做分布式缓存:使用lua API来访问redis缓存:使用nginx向客户端提 ...

  2. nginx+lua+redis构建高并发应用(转)

    nginx+lua+redis构建高并发应用 ngx_lua将lua嵌入到nginx,让nginx执行lua脚本,高并发,非阻塞的处理各种请求. url请求nginx服务器,然后lua查询redis, ...

  3. nginx限制请求之三:Nginx+Lua+Redis 对请求进行限制

    相关文章: <高可用服务设计之二:Rate limiting 限流与降级> <nginx限制请求之一:(ngx_http_limit_conn_module)模块> <n ...

  4. 基于nginx+lua+redis高性能api应用实践

    基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...

  5. nginx+lua+redis 处理APK包替换

    nginx + lua +redis 安装与使用入门: http://huoding.com/2012/08/31/156 nginx httpEchoModule : http://wiki.ngi ...

  6. nginx+lua+redis实现灰度发布_test

    nginx+lua+redis实现灰度发布: 灰度发布是指在黑白之间能够平滑过渡的一种方式 AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见, ...

  7. Nginx+Lua+Redis 对请求进行限制

    Nginx+Lua+Redis 对请求进行限制 一.概述 需求:所有访问/myapi/**的请求必须是POST请求,而且根据请求参数过滤不符合规则的非法请求(黑名单), 这些请求一律不转发到后端服务器 ...

  8. Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Discuz!

    Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Disc ...

  9. nginx lua redis 访问频率限制(转)

    1. 需求分析 Nginx来处理访问控制的方法有多种,实现的效果也有多种,访问IP段,访问内容限制,访问频率限制等. 用Nginx+Lua+Redis来做访问限制主要是考虑到高并发环境下快速访问控制的 ...

  10. nginx+lua+redis

    git clone --branch master https://github.com/openresty/lua-resty-redis.git yum install openssl opens ...

随机推荐

  1. .NET Core 泛型底层原理浅谈

    简介 泛型参考资料烂大街,基本资料不再赘述,比如泛型接口/委托/方法的使用,逆变与协变. 泛型好处有如下几点 代码重用 算法重用,只需要预先定义好算法,排序,搜索,交换,比较等.任何类型都可以用同一套 ...

  2. Matlab矩阵运算的硬件资源分析

    在用Matlab创建矩阵并计算矩阵乘法运算时,要注意计算机的可用内存大小(空间资源)和CPU性能(影响所用计算时间). 例如我们做以下测试:n为qubit的数目,那么一个矩阵Matrix_A=rand ...

  3. CubeIDE 主题美化与颜色设置

    一.主题美化 搜索引擎里很多,这里不必多说. 二.颜色设置 2.1.关于控制台 菜单栏里:window→preference→输入"console"并回车,然后按照下图指示来: 2 ...

  4. getExplorerInfo:获取浏览器信息

    function getExplorerInfo() { let t = navigator.userAgent.toLowerCase(); return 0 <= t.indexOf(&qu ...

  5. js-xlsx 前段读取excel

    JavaScript读取和导出excel示例(基于js-xlsx) 放入参考链接 http://demo.haoji.me/2017/02/08-js-xlsx/ github官网 https://g ...

  6. Air780E软件指南:C语言内存数组(zbuff)

    一.ZBUFF(C内存数组)简介 zbuff库可以用c风格直接操作(下标从0开始),例如buff[0]=buff[3] 可以在sram上或者psram上申请空间,也可以自动申请(如存在psram则在p ...

  7. Windows 自动色彩管理(ACM)

    在一些笔记本上Win11可以看到设置里有"自动管理应用的颜色"选项,有些笔记上没有.这里讲下"自动管理应用的颜色"的显示规则 看华为MetaBook E设置界面 ...

  8. Solr 的核心就是搜索

    原文  http://www.aptusource.org/2014/06/searching-is-what-its-all-about/ Solr 的主要功能就是强大的查询处理.在本文中,你将会看 ...

  9. Java方法参数太多怎么办—Part 1—自定义类型

    本文由 ImportNew - 王村平 翻译自 dzone.如需转载本文,请先参见文章末尾处的转载要求. 本文是这个系列的第一篇文章,介绍了采用自定义类型处理参数过多的问题.如果你也希望参与类似的系列 ...

  10. vue结合element UI做checkbox全选的tree结构

    由于element UI中的tree可能不能满足项目中的样式需求,所以自己动手结合element中的checkbox全选功能实现了一个符合项目需求的tree.效果如下: html部分: <tem ...