Redis的三种集群方案简介(Master, Slave, Sentinel, Cluster)

 redis  Redis的三种集群方案简介(Master, Slave, Sentinel, Cluster)已关闭评论
7月 292021
 

重温下redis集群的三种集群方案,分享下网络上的一篇文章,写的很好, 原文链接见文末。

 

在开发测试环境中,我们一般搭建Redis的单实例来应对开发测试需求,但是在生产环境,如果对可用性、可靠性要求较高,则需要引入Redis的集群方案。虽然现在各大云平台有提供缓存服务可以直接使用,但了解一下其背后的实现与原理总还是有些必要(比如面试), 本文就一起来学习一下Redis的几种集群方案。

Redis支持三种集群方案

  • 主从复制模式
  • Sentinel(哨兵)模式
  • Cluster模式

主从复制模式

1. 基本原理

主从复制模式中包含一个主数据库实例(master)与一个或多个从数据库实例(slave),如下图

redis-master-slave

客户端可对主数据库进行读写操作,对从数据库进行读操作,主数据库写入的数据会实时自动同步给从数据库。

具体工作机制为:

  1. slave启动后,向master发送SYNC命令,master接收到SYNC命令后通过bgsave保存快照(即上文所介绍的RDB持久化),并使用缓冲区记录保存快照这段时间内执行的写命令
  2. master将保存的快照文件发送给slave,并继续记录执行的写命令
  3. slave接收到快照文件后,加载快照文件,载入数据
  4. master快照发送完后开始向slave发送缓冲区的写命令,slave接收命令并执行,完成复制初始化
  5. 此后master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性

2. 部署示例

本示例基于Redis 5.0.3版。

redis.conf的主要配置

###网络相关###
# bind 127.0.0.1 # 绑定监听的网卡IP,注释掉或配置成0.0.0.0可使任意IP均可访问
protected-mode no # 关闭保护模式,使用密码访问
port 6379  # 设置监听端口,建议生产环境均使用自定义端口
timeout 30 # 客户端连接空闲多久后断开连接,单位秒,0表示禁用

###通用配置###
daemonize yes # 在后台运行
pidfile /var/run/redis_6379.pid  # pid进程文件名
logfile /usr/local/redis/logs/redis.log # 日志文件的位置

###RDB持久化配置###
save 900 1 # 900s内至少一次写操作则执行bgsave进行RDB持久化
save 300 10
save 60 10000 
# 如果禁用RDB持久化,可在这里添加 save ""
rdbcompression yes #是否对RDB文件进行压缩,建议设置为no,以(磁盘)空间换(CPU)时间
dbfilename dump.rdb # RDB文件名称
dir /usr/local/redis/datas # RDB文件保存路径,AOF文件也保存在这里

###AOF配置###
appendonly yes # 默认值是no,表示不使用AOF增量持久化的方式,使用RDB全量持久化的方式
appendfsync everysec # 可选值 always, everysec,no,建议设置为everysec

###设置密码###
requirepass 123456 # 设置复杂一点的密码

部署主从复制模式只需稍微调整slave的配置,在redis.conf中添加

replicaof 127.0.0.1 6379 # master的ip,port
masterauth 123456 # master的密码
replica-serve-stale-data no # 如果slave无法与master同步,设置成slave不可读,方便监控脚本发现问题

本示例在单台服务器上配置master端口6379,两个slave端口分别为7001,7002,启动master,再启动两个slave

[[email protected] master-slave]# redis-server master.conf
[[email protected] master-slave]# redis-server slave1.conf
[[email protected] master-slave]# redis-server slave2.conf

进入master数据库,写入一个数据,再进入一个slave数据库,立即便可访问刚才写入master数据库的数据。如下所示

[[email protected] master-slave]# redis-cli 
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set site blog.jboost.cn
OK
127.0.0.1:6379> get site
"blog.jboost.cn"
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=7001,state=online,offset=13364738,lag=1
slave1:ip=127.0.0.1,port=7002,state=online,offset=13364738,lag=0
...
127.0.0.1:6379> exit

[[email protected] master-slave]# redis-cli -p 7001
127.0.0.1:7001> auth 123456
OK
127.0.0.1:7001> get site
"blog.jboost.cn"

执行info replication命令可以查看连接该数据库的其它库的信息,如上可看到有两个slave连接到master

3. 主从复制的优缺点

优点:

  1. master能自动将数据同步到slave,可以进行读写分离,分担master的读压力
  2. master、slave之间的同步是以非阻塞的方式进行的,同步期间,客户端仍然可以提交查询或更新请求

缺点:

  1. 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
  2. master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
  3. 难以支持在线扩容,Redis的容量受限于单机配置

Sentinel(哨兵)模式

1. 基本原理

哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。如图

redis-sentinel

哨兵顾名思义,就是来为Redis集群站哨的,一旦发现问题能做出相应的应对处理。其功能包括

  1. 监控master、slave是否正常运行
  2. 当master出现故障时,能自动将一个slave转换为master(大哥挂了,选一个小弟上位)
  3. 多个哨兵可以监控同一个Redis,哨兵之间也会自动监控

哨兵模式的具体工作机制:

在配置文件中通过 sentinel monitor <master-name> <ip> <redis-port> <quorum> 来定位master的IP、端口,一个哨兵可以监控多个master数据库,只需要提供多个该配置项即可。哨兵启动后,会与要监控的master建立两条连接:

  1. 一条连接用来订阅master的_sentinel_:hello频道与获取其他监控该master的哨兵节点信息
  2. 另一条连接定期向master发送INFO等命令获取master本身的信息

与master建立连接后,哨兵会执行三个操作:

  1. 定期(一般10s一次,当master被标记为主观下线时,改为1s一次)向master和slave发送INFO命令
  2. 定期向master和slave的_sentinel_:hello频道发送自己的信息
  3. 定期(1s一次)向master、slave和其他哨兵发送PING命令

发送INFO命令可以获取当前数据库的相关信息从而实现新节点的自动发现。所以说哨兵只需要配置master数据库信息就可以自动发现其slave信息。获取到slave信息后,哨兵也会与slave建立两条连接执行监控。通过INFO命令,哨兵可以获取主从数据库的最新信息,并进行相应的操作,比如角色变更等。

接下来哨兵向主从数据库的_sentinel_:hello频道发送信息与同样监控这些数据库的哨兵共享自己的信息,发送内容为哨兵的ip端口、运行id、配置版本、master名字、master的ip端口还有master的配置版本。这些信息有以下用处:

  1. 其他哨兵可以通过该信息判断发送者是否是新发现的哨兵,如果是的话会创建一个到该哨兵的连接用于发送PING命令。
  2. 其他哨兵通过该信息可以判断master的版本,如果该版本高于直接记录的版本,将会更新
  3. 当实现了自动发现slave和其他哨兵节点后,哨兵就可以通过定期发送PING命令定时监控这些数据库和节点有没有停止服务。

如果被PING的数据库或者节点超时(通过 sentinel down-after-milliseconds master-name milliseconds 配置)未回复,哨兵认为其主观下线(sdown,s就是Subjectively —— 主观地)。如果下线的是master,哨兵会向其它哨兵发送命令询问它们是否也认为该master主观下线,如果达到一定数目(即配置文件中的quorum)投票,哨兵会认为该master已经客观下线(odown,o就是Objectively —— 客观地),并选举领头的哨兵节点对主从系统发起故障恢复。若没有足够的sentinel进程同意master下线,master的客观下线状态会被移除,若master重新向sentinel进程发送的PING命令返回有效回复,master的主观下线状态就会被移除

哨兵认为master客观下线后,故障恢复的操作需要由选举的领头哨兵来执行,选举采用Raft算法:

  1. 发现master下线的哨兵节点(我们称他为A)向每个哨兵发送命令,要求对方选自己为领头哨兵
  2. 如果目标哨兵节点没有选过其他人,则会同意选举A为领头哨兵
  3. 如果有超过一半的哨兵同意选举A为领头,则A当选
  4. 如果有多个哨兵节点同时参选领头,此时有可能存在一轮投票无竞选者胜出,此时每个参选的节点等待一个随机时间后再次发起参选请求,进行下一轮投票竞选,直至选举出领头哨兵

选出领头哨兵后,领头者开始对系统进行故障恢复,从出现故障的master的从数据库中挑选一个来当选新的master,选择规则如下:

  1. 所有在线的slave中选择优先级最高的,优先级可以通过slave-priority配置
  2. 如果有多个最高优先级的slave,则选取复制偏移量最大(即复制越完整)的当选
  3. 如果以上条件都一样,选取id最小的slave

挑选出需要继任的slave后,领头哨兵向该数据库发送命令使其升格为master,然后再向其他slave发送命令接受新的master,最后更新数据。将已经停止的旧的master更新为新的master的从数据库,使其恢复服务后以slave的身份继续运行。

2. 部署演示

本示例基于Redis 5.0.3版。

哨兵模式基于前文的主从复制模式。哨兵的配置文件为sentinel.conf,在文件中添加

sentinel monitor mymaster 127.0.0.1 6379 1 # mymaster定义一个master数据库的名称,后面是master的ip, port,1表示至少需要一个Sentinel进程同意才能将master判断为失效,如果不满足这个条件,则自动故障转移(failover)不会执行
sentinel auth-pass mymaster 123456 # master的密码

sentinel down-after-milliseconds mymaster 5000 # 5s未回复PING,则认为master主观下线,默认为30s
sentinel parallel-syncs mymaster 2  # 指定在执行故障转移时,最多可以有多少个slave实例在同步新的master实例,在slave实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
sentinel failover-timeout mymaster 300000 # 如果在该时间(ms)内未能完成故障转移操作,则认为故障转移失败,生产环境需要根据数据量设置该值

一个哨兵可以监控多个master数据库,只需按上述配置添加多套

分别以26379,36379,46379端口启动三个sentinel

[[email protected] sentinel]# redis-server sentinel1.conf --sentinel
[[email protected] sentinel]# redis-server sentinel2.conf --sentinel
[[email protected] sentinel]# redis-server sentinel3.conf --sentinel

也可以使用redis-sentinel sentinel1.conf 命令启动。此时集群包含一个master、两个slave、三个sentinel,如图,

redis-cluster-instance

我们来模拟master挂掉的场景,执行 kill -9 3017 将master进程干掉,进入slave中执行 info replication查看,

[[email protected] sentinel]# redis-cli -p 7001
127.0.0.1:7001> auth 123456
OK
127.0.0.1:7001> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:7002
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
# 省略
127.0.0.1:7001> exit
[[email protected] sentinel]# redis-cli -p 7002
127.0.0.1:7002> auth 123456
OK
127.0.0.1:7002> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=7001,state=online,offset=13642721,lag=1
# 省略

可以看到slave 7002已经成功上位晋升为master(role:master),接收一个slave 7001的连接。此时查看slave2.conf配置文件,发现replicaof的配置已经被移除了,slave1.conf的配置文件里replicaof 127.0.0.1 6379 被改为 replicaof 127.0.0.1 7002。重新启动master,也可以看到master.conf配置文件中添加了replicaof 127.0.0.1 7002的配置项,可见大哥(master)下位后,再出来混就只能当当小弟(slave)了,三十年河东三十年河西。

3. 哨兵模式的优缺点

优点:

  1. 哨兵模式基于主从复制模式,所以主从复制模式有的优点,哨兵模式也有
  2. 哨兵模式下,master挂掉可以自动进行切换,系统可用性更高

缺点:

  1. 同样也继承了主从模式难以在线扩容的缺点,Redis的容量受限于单机配置
  2. 需要额外的资源来启动sentinel进程,实现相对复杂一点,同时slave节点作为备份节点不提供服务

Cluster模式

1. 基本原理

哨兵模式解决了主从复制不能自动故障转移,达不到高可用的问题,但还是存在难以在线扩容,Redis容量受限于单机配置的问题。Cluster模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题。如图

redis-cluster

Cluster采用无中心结构,它的特点如下:

  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效
  3. 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

Cluster模式的具体工作机制:

  1. 在Redis的每个节点上,都有一个插槽(slot),取值范围为0-16383
  2. 当我们存取key的时候,Redis会根据CRC16的算法得出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
  3. 为了保证高可用,Cluster模式也引入主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点
  4. 当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点都宕机了,那么该集群就无法再提供服务了

Cluster模式集群节点最小配置6个节点(3主3从,因为需要半数以上),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。

2. 部署演示

本示例基于Redis 5.0.3版。

Cluster模式的部署比较简单,首先在redis.conf中

port 7100 # 本示例6个节点端口分别为7100,7200,7300,7400,7500,7600 
daemonize yes # r后台运行 
pidfile /var/run/redis_7100.pid # pidfile文件对应7100,7200,7300,7400,7500,7600 
cluster-enabled yes # 开启集群模式 
masterauth passw0rd # 如果设置了密码,需要指定master密码
cluster-config-file nodes_7100.conf # 集群的配置文件,同样对应7100,7200等六个节点
cluster-node-timeout 15000 # 请求超时 默认15秒,可自行设置 

分别以端口7100,7200,7300,7400,7500,7600 启动六个实例(如果是每个服务器一个实例则配置可一样)

[[email protected] cluster]# redis-server redis_7100.conf
[[email protected] cluster]# redis-server redis_7200.conf
...

然后通过命令将这个6个实例组成一个3主节点3从节点的集群,

redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7100 127.0.0.1:7200 127.0.0.1:7300 127.0.0.1:7400 127.0.0.1:7500 127.0.0.1:7600 -a passw0rd

执行结果如图

redis-cluster-deploy

可以看到 7100, 7200, 7300 作为3个主节点,分配的slot分别为 0-5460, 5461-10922, 10923-16383, 7600作为7100的slave, 7500作为7300的slave,7400作为7200的slave。

我们连接7100设置一个值

[[email protected] cluster]# redis-cli -p 7100 -c -a passw0rd
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:7100> set site blog.jboost.cn
-> Redirected to slot [9421] located at 127.0.0.1:7200
OK
127.0.0.1:7200> get site
"blog.jboost.cn"
127.0.0.1:7200>

注意添加 -c 参数表示以集群模式,否则报 (error) MOVED 9421 127.0.0.1:7200 错误, 以 -a 参数指定密码,否则报(error) NOAUTH Authentication required错误。

从上面命令看到key为site算出的slot为9421,落在7200节点上,所以有Redirected to slot [9421] located at 127.0.0.1:7200,集群会自动进行跳转。因此客户端可以连接任何一个节点来进行数据的存取。

通过cluster nodes可查看集群的节点信息

127.0.0.1:7200> cluster nodes
eb28aaf090ed1b6b05033335e3d90a202b422d6c 127.0.0.1:[email protected] slave c1047de2a1b5d5fa4666d554376ca8960895a955 0 1584165266071 5 connected
4cc0463878ae00e5dcf0b36c4345182e021932bc 127.0.0.1:[email protected] slave 5544aa5ff20f14c4c3665476de6e537d76316b4a 0 1584165267074 4 connected
dbbb6420d64db22f35a9b6fa460b0878c172a2fb 127.0.0.1:[email protected] master - 0 1584165266000 1 connected 0-5460
d4b434f5829e73e7e779147e905eea6247ffa5a2 127.0.0.1:[email protected] slave dbbb6420d64db22f35a9b6fa460b0878c172a2fb 0 1584165265000 6 connected
5544aa5ff20f14c4c3665476de6e537d76316b4a 127.0.0.1:[email protected] myself,master - 0 1584165267000 2 connected 5461-10922
c1047de2a1b5d5fa4666d554376ca8960895a955 127.0.0.1:[email protected] master - 0 1584165268076 3 connected 10923-16383

我们将7200通过 kill -9 pid杀死进程来验证集群的高可用,重新进入集群执行cluster nodes可以看到7200 fail了,但是7400成了master,重新启动7200,可以看到此时7200已经变成了slave。

3. Cluster模式的优缺点

优点:

  1. 无中心架构,数据按照slot分布在多个节点。
  2. 集群中的每个节点都是平等的关系,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
  3. 可线性扩展到1000多个节点,节点可动态添加或删除
  4. 能够实现自动故障转移,节点之间通过gossip协议交换状态信息,用投票机制完成slave到master的角色转换

缺点:

  1. 客户端实现复杂,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,提高了开发难度。目前仅JedisCluster相对成熟,异常处理还不完善,比如常见的“max redirect exception”
  2. 节点会因为某些原因发生阻塞(阻塞时间大于 cluster-node-timeout)被判断下线,这种failover是没有必要的
  3. 数据通过异步复制,不保证数据的强一致性
  4. slave充当“冷备”,不能缓解读压力
  5. 批量操作限制,目前只支持具有相同slot值的key执行批量操作,对mset、mget、sunion等操作支持不友好
  6. key事务操作支持有线,只支持多key在同一节点的事务操作,多key分布不同节点时无法使用事务功能
  7. 不支持多数据库空间,单机redis可以支持16个db,集群模式下只能使用一个,即db 0

Redis Cluster模式不建议使用pipeline和multi-keys操作,减少max redirect产生的场景。

总结

本文介绍了Redis集群方案的三种模式,其中主从复制模式能实现读写分离,但是不能自动故障转移;哨兵模式基于主从复制模式,能实现自动故障转移,达到高可用,但与主从复制模式一样,不能在线扩容,容量受限于单机的配置;Cluster模式通过无中心化架构,实现分布式存储,可进行线性扩展,也能高可用,但对于像批量操作、事务操作等的支持性不够好。三种模式各有优缺点,可根据实际场景进行选择。

 

转自:https://segmentfault.com/a/1190000022028642

9个提升逼格的redis命令(keys,scan,slowlog,rename-command,bigkeys,monitor,info,config,set)

 redis  9个提升逼格的redis命令(keys,scan,slowlog,rename-command,bigkeys,monitor,info,config,set)已关闭评论
9月 082020
 

9个提升逼格的redis命令

非常好的文章,特别是使用bigkeys查找占大内存的key真是方便,推荐https://www.jianshu.com/p/4df5f2356de9

keys

我把这个命令放在第一位,是因为笔者曾经做过的项目,以及一些朋友的项目,都因为使用keys这个命令,导致出现性能毛刺。这个命令的时间复杂度是O(N),而且redis又是单线程执行,在执行keys时即使是时间复杂度只有O(1)例如SET或者GET这种简单命令也会堵塞,从而导致这个时间点性能抖动,甚至可能出现timeout。

强烈建议生产环境屏蔽keys命令(后面会介绍如何屏蔽)。

scan

既然keys命令不允许使用,那么有什么代替方案呢?有!那就是scan命令。如果把keys命令比作类似select * from users where username like '%afei%'这种SQL,那么scan应该是select * from users where id>? limit 10这种命令。

官方文档用法如下:

SCAN cursor [MATCH pattern] [COUNT count]

初始执行scan命令例如scan 0。SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。当SCAN命令的游标参数被设置为0时,服务器将开始一次新的迭代,而当redis服务器向用户返回值为0的游标时,表示迭代已结束,这是唯一迭代结束的判定方式,而不能通过返回结果集是否为空判断迭代结束。

使用方式:

127.0.0.1:6380> scan 0
1) "22"
2)  1) "23"
    2) "20"
    3) "14"
    4) "2"
    5) "19"
    6) "9"
    7) "3"
    8) "21"
    9) "12"
   10) "25"
   11) "7"

返回结果分为两个部分:第一部分即1)就是下一次迭代游标,第二部分即2)就是本次迭代结果集。

slowlog

上面提到不能使用keys命令,如果就有开发这么做了呢,我们如何得知?与其他任意存储系统例如mysql,mongodb可以查看慢日志一样,redis也可以,即通过命令slowlog。用法如下:

SLOWLOG subcommand [argument]

subcommand主要有:

  • get,用法:slowlog get [argument],获取argument参数指定数量的慢日志。
  • len,用法:slowlog len,总慢日志数量。
  • reset,用法:slowlog reset,清空慢日志。

执行结果如下:

127.0.0.1:6380> slowlog get 5
1) 1) (integer) 2
   2) (integer) 1532656201
   3) (integer) 2033
   4) 1) "flushddbb"
2) 1) (integer) 1  ----  慢日志编码,一般不用care
   2) (integer) 1532646897  ----  导致慢日志的命令执行的时间点,如果api有timeout,可以通过对比这个时间,判断可能是慢日志命令执行导致的
   3) (integer) 26424  ----  导致慢日志执行的redis命令,通过4)可知,执行config rewrite导致慢日志,总耗时26ms+
   4) 1) "config"
      2) "rewrite"

命令耗时超过多少才会保存到slowlog中,可以通过命令config set slowlog-log-slower-than 2000配置并且不需要重启redis。注意:单位是微妙,2000微妙即2毫秒。

rename-command

为了防止把问题带到生产环境,我们可以通过配置文件重命名一些危险命令,例如keys等一些高危命令。操作非常简单,只需要在conf配置文件增加如下所示配置即可:

rename-command flushdb flushddbb
rename-command flushall flushallall
rename-command keys keysys

bigkeys

随着项目越做越大,缓存使用越来越不规范。我们如何检查生产环境上一些有问题的数据。bigkeys就派上用场了,用法如下:

redis-cli -p 6380 --bigkeys

执行结果如下:

... ...
-------- summary -------

Sampled 526 keys in the keyspace!
Total key length in bytes is 1524 (avg len 2.90)

Biggest string found 'test' has 10005 bytes
Biggest   list found 'commentlist' has 13 items

524 strings with 15181 bytes (99.62% of keys, avg size 28.97)
2 lists with 19 items (00.38% of keys, avg size 9.50)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00)

最后5行可知,没有set,hash,zset几种数据结构的数据。string类型有524个,list类型有两个;通过Biggest ... ...可知,最大string结构的key是test,最大list结构的key是commentlist

需要注意的是,这个bigkeys得到的最大,不一定是最大。说明原因前,首先说明bigkeys的原理,非常简单,通过scan命令遍历,各种不同数据结构的key,分别通过不同的命令得到最大的key:

  • 如果是string结构,通过strlen判断;
  • 如果是list结构,通过llen判断;
  • 如果是hash结构,通过hlen判断;
  • 如果是set结构,通过scard判断;
  • 如果是sorted set结构,通过zcard判断。

正因为这样的判断方式,虽然string结构肯定可以正确的筛选出最占用缓存,也可以说最大的key。但是list不一定,例如,现在有两个list类型的key,分别是:numberlist–[0,1,2],stringlist–[“123456789123456789”],由于通过llen判断,所以numberlist要大于stringlist。而事实上stringlist更占用内存。其他三种数据结构hash,set,sorted set都会存在这个问题。使用bigkeys一定要注意这一点。

monitor

假设生产环境没有屏蔽keys等一些高危命令,并且slowlog中还不断有新的keys导致慢日志。那我们如何揪出这些命令是由谁执行的呢?这就是monitor的用处,用法如下:

redis-cli -p 6380 monitor

如果当前redis环境OPS比较高,那么建议结合linux管道命令优化,只输出keys命令的执行情况:

[[email protected] ~]# redis-cli -p 6380 monitor | grep keys 
1532645266.656525 [0 10.0.0.1:43544] "keyss" "*"
1532645287.257657 [0 10.0.0.1:43544] "keyss" "44*"

执行结果中很清楚的看到keys命名执行来源。通过输出的IP和端口信息,就能在目标服务器上找到执行这条命令的进程,揪出元凶,勒令整改。

info

如果说哪个命令能最全面反映当前redis运行情况,那么非info莫属。用法如下:

INFO [section]

section可选值有:

  • Server:运行的redis实例一些信息,包括:redis版本,操作系统信息,端口,GCC版本,配置文件路径等;
  • Clients:redis客户端信息,包括:已连接客户端数量,阻塞客户端数量等;
  • Memory:使用内存,峰值内存,内存碎片率,内存分配方式。这几个参数都非常重要;
  • Persistence:AOF和RDB持久化信息;
  • Stats:一些统计信息,最重要三个参数:OPS(instantaneous_ops_per_sec),keyspace_hitskeyspace_misses两个参数反应缓存命中率;
  • Replication:redis集群信息;
  • CPU:CPU相关信息;
  • Keyspace:redis中各个DB里key的信息;

config

config是一个非常有价值的命令,主要体现在对redis的运维。因为生产环境一般是不允许随意重启的,不能因为需要调优一些参数就修改conf配置文件并重启。redis作者早就想到了这一点,通过config命令能热修改一些配置,不需要重启redis实例,可以通过如下命令查看哪些参数可以热修改:

config get *

热修改就比较容易了,执行如下命令即可:

config set 

例如:config set slowlog-max-len 100config set maxclients 1024

这样修改的话,如果以后由于某些原因redis实例故障需要重启,那通过config热修改的参数就会被配置文件中的参数覆盖,所以我们需要通过一个命令将config热修改的参数刷到redis配置文件中持久化,通过执行如下命令即可:

config rewrite

执行该命令后,我们能在config文件中看到类似这种信息:

# 如果conf中本来就有这个参数,通过执行config set,那么redis直接原地修改配置文件
maxclients 1024
# 如果conf中没有这个参数,通过执行config set,那么redis会追加在Generated by CONFIG REWRITE字样后面
# Generated by CONFIG REWRITE
save 600 60
slowlog-max-len 100

set

set命令也能提升逼格?是的,我本不打算写这个命令,但是我见过太多人没有完全掌握这个命令,官方文档介绍的用法如下:

SET key value [EX seconds] [PX milliseconds] [NX|XX]

你可能用的比较多的就是set key value,或者SETEX key seconds value,所以很多同学用redis实现分布式锁分为两步:首先执行SETNX key value,然后执行EXPIRE key seconds。很明显,这种实现有很严重的问题,因为两步执行不具备原子性,如果执行第一个命令后出现某些未知异常导致无法执行EXPIRE key seconds,那么分布式锁就会一直无法得到释放。

通过SET命令实现分布式锁的正式姿势应该是SET key value EX seconds NX(EX和PX任选,取决于对过期时间精度要求)。另外,value也有要求,最好是一个类似UUID这种具备唯一性的字符串。当然如果问你redis是否还有其他实现分布式锁的方案。你能说出redlock,那对方一定眼前一亮,心里对你竖起大拇指,但嘴上不会说。

redis数据迁移的3个方法

 redis  redis数据迁移的3个方法已关闭评论
1月 172020
 

1. rdb数据备份恢复方法
redis 127.0.0.1:6379> SAVE
OK
或者
redis-cli -h 127.0.0.1 -p 6379 -a pwd bgsave
该命令将在 redis 安装目录中创建dump.rdb文件。

查找dump.rdb文件位置
redis 127.0.0.1:6379> CONFIG GET dir
1) dir
2) /usr/local/redis/bin
以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin
bgsave
创建 redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行。
127.0.0.1:6379> BGSAVE
Background saving started

2. AOF数据备份恢复方法
另一种持久化方式AOF,在配置文件中打开[appendonly yes]。
AOF刷新日志到disk的规则:
appendfsync always #always 表示每次有写操作都进行同步,非常慢,非常安全。
appendfsync everysec #everysec表示对写操作进行累积,每秒同步一次
官方的建议的everysec,安全,就是速度不够快,如果是机器出现问题可能会丢失1秒的数据。

也可以手动执行bgrewriteaof进行AOF备份:
redis-cli -h 127.0.0.1 -p 6379 -a pwd bgrewriteaof

迁移数据恢复
迁移到另外一台恢复数据,需先检查配置文件,将按照以下优先级恢复数据到内存:
如果只配置AOF,重启时加载AOF文件恢复数据;
如果同时 配置了RBDAOF,启动是只加载AOF文件恢复数据;
如果只配置RBD,启动是讲加载dump文件恢复数据;

dump.rdb或者AOF文件迁移到另外一台恢复数据
恢复数据,只需将备份文件 (dump.rdb或者AOF文件) 移动到 redis 安装目录并启动服务即可。

3. redis从库复制数据方法
Redis提供了复制(replication)功能可以自动实现同步的过程。
配置方法
通过配置文件 从数据库的配置文件中加入slaveof master-ip master-port,主数据库无需配置
通过命令行参数 启动redis-server的时候,使用命令行参数–slaveof master-ip master port
redis-server –port 6380 –slaveof 127.0.0.1 6379
通过命令SLAVEOF master-ip master-port
redis>SLAVEOF 127.0.0.1 6379
SLAVEOF NO ONE可以是当前数据库停止接收其他数据库的同步,转成主Redis数据库,程序连接地址都改为新的redisIP地址和端口。

转自:https://my.oschina.net/ppabvc/blog/819448

mac 下 redis 安装、redis.conf位置、redis-server后台运行

 redis  mac 下 redis 安装、redis.conf位置、redis-server后台运行已关闭评论
11月 122019
 

mac下安装redis命令:

brew install redis

 

如果没有安装homebrew,可以打开一个终端,输入下面命令安装:

/usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”

 

启动:

redis-server 命令直接启动会运行在一个终端里,关闭终端服务就停止了,也没有运行参数可以后台运行,但可以通过修改配置文件参数实现。

mac下brew安装的redis的配置文件默认所在位置: /usr/local/etc/redis.conf

修改: 将 daemonize no 修改为 daemonize yes

 

再启动

redis-server /usr/local/etc/redis.conf

redis就会后台运行了

 

如果要开机启动,使用下面命令:

ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

brew services start redis

SpringBoot整合Redis和StringRedisTemplate的使用

 spring, spring-boot  SpringBoot整合Redis和StringRedisTemplate的使用已关闭评论
1月 212019
 

springboot下使用redis非常方便:


Maven依赖

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-redis</artifactId>

    <!– <artifactId>spring-boot-starter-redis</artifactId> –>    

</dependency>

 

配置文件 application.properties添加

#redis的ip地址 

spring.redis.hostName=127.0.0.1

#数据库,默认为0

spring.redis.database=1

#端口号 

spring.redis.port=6379

#如果有密码 

spring.redis.password=xxxxx

#客户端超时时间单位是毫秒 默认是2000

spring.redis.timeout=20000 

 

StringRedisTemplate使用

stringRedisTemplate.opsForValue();//操作字符串

stringRedisTemplate.opsForHash();//操作hash

stringRedisTemplate.opsForList();//操作list

stringRedisTemplate.opsForSet();//操作set

stringRedisTemplate.opsForZSet();//操作有序set

示例

import
org.springframework.beans.factory.annotation.Autowired;

import
org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.stereotype.Service;

 

import java.util.concurrent.TimeUnit;

 

@Service

public class RedisService {

    @Autowired

   
StringRedisTemplate stringRedisTemplate;

 

    /**

     *
stringRedisTemplate基本操作

     */

    public void redis(){

       
stringRedisTemplate.opsForValue().set(“key”, “value”,60*10,
TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间(10分钟)

       
stringRedisTemplate.boundValueOps(“key”).increment(1);//val做1操作

       
stringRedisTemplate.opsForValue().get(“key”);//根据key获取缓存中的val

       
stringRedisTemplate.boundValueOps(“key”).increment(1);//val +1

       
stringRedisTemplate.getExpire(“key”);//根据key获取过期时间

       
stringRedisTemplate.getExpire(“key”,TimeUnit.SECONDS);//根据key获取过期时间并换算成指定单位

       
stringRedisTemplate.delete(“key”);//根据key删除缓存

       
stringRedisTemplate.hasKey(“key”);//检查key是否存在,返回boolean

       
stringRedisTemplate.opsForSet().add(“key”, “5”,”6″,”7″);//向指定key中存放set集合

       
stringRedisTemplate.expire(“key”,1000 ,
TimeUnit.MILLISECONDS);//设置过期时间

       
stringRedisTemplate.opsForSet().isMember(“key”, “1”);//根据key查看集合中是否存在指定数据

       
stringRedisTemplate.opsForSet().members(“key”);//根据key获取set集合

 

    }

}

 

 

celery使用redis队列实例(celery使用入门)

 python  celery使用redis队列实例(celery使用入门)已关闭评论
6月 222016
 


Celery 是一个广泛应用于网络应用程序的任务处理系统。


它可以在以下情况下使用:


在请求响应周期中做网络调用

服务器应当立即响应任何网络请求。如果在请求响应周期内需要进行网络调用,则应在周期外完成调用。例如当用户在网站上注册时,需要发送激活邮件。发送邮件是一种网络调用,耗时2到3秒。用户应该无需等待这2到3秒。因此,发送激活邮件应当在请求响应周期外完成,celery 就能实现这一点。


将一个由几个独立部分组成的大任务分成多个小任务

假设你想知道脸书用户的时间流。脸书提供不同的端点来获取不同的数据。譬如,一个端点用以获取用户时间流中的图片,一个端点获取用户时间流中的博文,一个端点得到用户的点赞信息等。如果你的函数需要和脸书的5个端点依此通信,每个网络调用平均耗时2秒,你将需要10秒完成一次函数执行。但是,你可以把这项工作分为5个独立的任务(你很快就会发现这很容易做到),并让 celery 来处理这些任务。Celery 可以并行地与这5个端点通信,在2秒之内就能得到所有端点的响应。


简单的 celery 例子


假设我们有一个函数,并传给它一个网址列表。该函数需要获取这些网址的响应。


没有使用 celery


创建文件celery_blog.py


import requests  
import time

def func(urls):  
    start = time.time()
    for url in urls:
        resp = requests.get(url)
        print resp.status_code
    print "It took", time.time() - start, "seconds"

if __name__ == "__main__":  
    func(["http://oneapm.com", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://news.oneapm.com"])


运行:


python celery_blog.py 


输出:


使用 celery


调用 celery 的程序中最重要的组成部分为 celery worker。


在 web 应用程序注册的例子中,celery worker 用于发送邮件。


在脸书的例子中, celery worker 用于获取不同的网址。


在我们的 celery_blog.py 例子中, celery worker 用于获取 URL。

celery worker 和你的应用程序/脚本是不同的进程,彼此独立运行。所以你的应用程序/脚本和 celery 需要一些方法来相互沟通。


应用程序代码需要把任务放在 celery worker 可以取出并执行的位置。

譬如,应用程序代码将任务放在消息队列中,celery worker 从消息队列领取任务并执行任务。我们将使用 Redis 作为消息队列。


请确认你已安装 Redis,并可以运行redis-server


请确认你已安装 celery。


修改文件 celery_blog.py,如下:


from celery import Celery

app = Celery('celery_blog',bloker='redis://localhost:6379/1')

@app.task
def fetch_url(url):  
     resp = requests.get(url)
     print resp.status_code

def func(urls):  
     for url in urls:
       fetch_url.delay(url)

if __name__ == "__main__":  
     func(["http://oneapm.com", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://news.oneapm.com"])

代码解释:我们需要一个 celery 实例来启动程序,因此创建了一个名为 app 的 celery 实例。


在3个终端中启动:


第一个终端,运行 redis-server


第二个终端,运行 celery worker -A celery_blog -l info -c 5 ,通过输出可以看到 celery 成功运行。


第三个终端,运行脚本 python celery_blog.py


可以看到第二个终端输出如下:



将 celery 代码和配置保存在不同文件中


上面的例子中,我们只写了一个 celery 任务。但您的项目可能涉及多个模块,您可能希望在不同的模块中有不同的任务。所以让我们将 celery 配置移到单独的文件中。


创建 celery_config.py

from celery import Celery

app = Celery('celery_config', broker='redis://localhost:6379/0', include=['celery_blog']) 

修改 celery_blog.py 代码如下:

import  requests  
from celery_config import app

@app.task
def fetch_url(url):  
     resp = requests.get(url)
     print resp.status_code

def func(urls):  
    for url in urls:
       fetch_url.delay(url)

if __name__ == "__main__":  
    func(["http://oneapm.com", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://news.oneapm.com"])

停掉之前的 celery worker ,运行:


celery worker -A celery_config -l info -c 5 

打开 ipython ,运行如下命令:


In [1]: from celery_blog import func  
In [2]: func(["http://oneapm.com", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://news.oneapm.com"]) 

输出如下:




在不同文件中添加新的任务


您可以添加新的模块,并在该模块中定义一个任务。用以下内容创建一个模块 celery_add.py


from celery_config import app

@app.task
def add(a, b):  
    return a + b


改变 celery_config.py 包含新的模块 celery_add.py,如下:


from celery import Celery

app = Celery('celery_config', broker='redis://localhost:6379/0', include=['celery_blog', 'celery_add']) 


在 ipython 输入:

In [1]: from celery_add import add  
In [2]: add.delay(4, 5) 


输出如下:



在不同的机器上分开使用 Redis 和 celery


到目前为止,我们的脚本、celery worker 和 Redis 都运行在同一机器中。其实并无这种必要,这三者可以运行在不同机器上。


celery 任务涉及到网络请求,因此,在网络优化的机器上使用 celery worker 能提高任务运行速度。Redis 是一种内存数据库,在内存优化的机器上运行效率更高。


在这个例子中,我将在本地系统运行脚本和 celery worker,在分开的服务器上运行 Redis。


修改 celery_config.py 为:


app = Celery('celery_config', broker='redis://192.168.118.148:6379/0', include=['celery_blog']) 

现在我运行任何任务,脚本都将把他放在 Redis 运行的服务器(192.168.118.148)上面。


celery worker 也与 192.168.118.148 沟通,在这个 Redis 服务器上得到任务并执行它。


自己把添加任务的脚本使用下面的方式独立调用:

from celery import Celery

app=Celery(broker=’redis://localhost:6379/1′)

app.send_task("celery_add.add", args=(1000, 2000))

这样似乎就可以真正分开独立了


转自:http://www.wtoutiao.com/p/C980i9.html

英文原文章:http://agiliq.com/blog/2015/07/getting-started-with-celery-and-redis/

redis 用setbit(bitmap)统计活跃用户

 开发  redis 用setbit(bitmap)统计活跃用户已关闭评论
9月 302015
 

本文来自Spool的开发者博客,描述了Spool利用Redisbitmaps相关的操作,进行网站活跃用户统计工作。

Redis支持对String类型的value进行基于二进制位的置位操作。通过将一个用户的id对应value上的一位,通过对活跃用户对应的位进行置位,就能够用一个value记录所有活跃用户的信息。如下图所未,下图中的bitmap有9个位被置为1,表示这9个位上对应的用户是今天的活跃用户。其中第15位表示uid为15的用户,第一位表示uid为0的用户。(如果你的uid不是从1开始的,比如从100000开始,实际上你也可以相应的用uid减去初始值来表示其位数,比如1000000用户对应到bitmap的第一位)

具体的代码类似下面这样:

redis.setbit(play:yyyy-mm-dd, user_id, 1)

这样一次记录的复杂度是O(1),在Redis中速度非常快。
而我们通过每天换用一个不同的key来将每天的活跃用户状态记录分开存。并且可以通过一些与或运算计算出N天活跃用户,和连接N天活跃用户这样的统计数据。
如下图,第一行表示星期一的活跃用户情况,第二行表示周二的,以此类推。为样我们通过对N天的活跃用户记录取并集操作,就能得出在N天内活跃过的用户列表。

下面表格表示对应一天,一周,一个月统计时所花费的时间。

Period Time (ms)
Daily 50.2
Weekly 392.0
Monthly 1624.8

下面是具体的java代码片断:

1.算出一天的活跃用户数量

import redis.clients.jedis.Jedis;
import java.util.BitSet;
...
  Jedis redis = new Jedis("localhost");
...
  public int uniqueCount(String action, String date) {
    String key = action + ":" + date;
    BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
    return users.cardinality();
  }

2.计算某几个内活跃用户的数量(某一天活跃就算,所以是取并集)

import redis.clients.jedis.Jedis;
import java.util.BitSet;
...
  Jedis redis = new Jedis("localhost");
...
  public int uniqueCount(String action, String... dates) {
    BitSet all = new BitSet();
    for (String date : dates) {
      String key = action + ":" + date;
      BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
      all.or(users);
    }
    return all.cardinality();
  }

具体的用法还很多,比如你还可以对独特终端的用户单独记一个bitmap,这样就可以统计不同终端用户的活跃情况。有的同学会说用set也能实现同样的效果。但使用set在内存使用量上是会大很多的。

一网打尽当下NoSQL类型、适用场景及使用公司

 未分类  一网打尽当下NoSQL类型、适用场景及使用公司已关闭评论
7月 092015
 

摘要:对比传统关系型数据库,NoSQL有着更为复杂的分类——键值、面向文档、列存储以及图数据库。这里就带你一览NoSQL各种类型的适用场景及一些知名公司的方案选择。

在过去几年,关系型数据库一直是数据持久化的唯一选择,数据工作者考虑的也只是在这些传统数据库中做筛选,比如SQL Server、Oracle或者是MySQL。甚至是做一些默认的选择,比如使用.NET的一般会选择SQL Server;使用Java的可能会偏向Oracle,Ruby是MySQL,Python则是PostgreSQL或MySQL等等。

原因很简单:过去很长一段时间内,关系数据库的健壮性已经在多数应用程序中得到证实。我们可以使用这些传统数据库良好的控制并发操作、事务等等。然而如果传统的关系型数据库一直这么可靠,那么还有NoSQL什么事?NoSQL之所以生存并得到发展,是因为它做到了传统关系型数据库做不到的事!

关系型数据库中存在的问题

Impedance Mismatch

 

我们使用Python、Ruby、Java、.Net等语言编写应用程序,这些语言有一个共同的特性——面向对象。但是我们使用MySQL、PostgreSQL、Oracle以及SQL Server,这些数据库同样有一个共同的特性——关系型数据库。这里就牵扯到了“Impedance Mismatch”这个术语:存储结构是面向对象的,但是数据库却是关系的,所以在每次存储或者查询数据时,我们都需要做转换。类似Hibernate、Entity Framework这样的ORM框架确实可以简化这个过程,但是在对查询有高性能需求时,这些ORM框架就捉襟见肘了。

应用程序规模的变大

网络应用程序的规模日渐变大,我们需要储存更多的数据、服务更多的用户以及需求更多的计算能力。为了应对这种情形,我们需要不停的扩展。扩展分为两类:一种是纵向扩展,即购买更好的机器,更多的磁盘、更多的内存等等;另一种是横向扩展,即购买更多的机器组成集群。在巨大的规模下,纵向扩展发挥的作用并不是很大。首先单机器性能提升需要巨额的开销并且有着性能的上限,在Google和Facebook这种规模下,永远不可能使用一台机器支撑所有的负载。鉴于这种情况,我们需要新的数据库,因为关系数据库并不能很好的运行在集群上。不错你也可能会去搭建关系数据库集群,但是他们使用的是共享存储,这并不是我们想要的类型。于是就有了以Google、Facebook、Amazon这些试图处理更多传输所引领的NoSQL纪元。

NoSQL纪元

当下已经存在很多的NoSQL数据库,比如MongoDB、Redis、Riak、HBase、Cassandra等等。每一个都拥有以下几个特性中的一个:

  • 不再使用SQL语言,比如MongoDB、Cassandra就有自己的查询语言
  • 通常是开源项目
  • 为集群运行而生
  • 弱结构化——不会严格的限制数据结构类型

NoSQL数据库的类型

NoSQL可以大体上分为4个种类:Key-value、Document-Oriented、Column-Family Databases以及 Graph-Oriented Databases。下面就一览这些类型的特性:

一、 键值(Key-Value)数据库

键值数据库就像在传统语言中使用的哈希表。你可以通过key来添加、查询或者删除数据,鉴于使用主键访问,所以会获得不错的性能及扩展性。

产品:Riak、Redis、Memcached、Amazon’s Dynamo、Project Voldemort

有谁在使用:GitHub (Riak)、BestBuy (Riak)、Twitter (Redis和Memcached)、StackOverFlow (Redis)、 Instagram (Redis)、Youtube (Memcached)、Wikipedia(Memcached)

适用的场景

储存用户信息,比如会话、配置文件、参数、购物车等等。这些信息一般都和ID(键)挂钩,这种情景下键值数据库是个很好的选择。

不适用场景

1. 取代通过键查询,而是通过值来查询。Key-Value数据库中根本没有通过值查询的途径。

2. 需要储存数据之间的关系。在Key-Value数据库中不能通过两个或以上的键来关联数据。

3. 事务的支持。在Key-Value数据库中故障产生时不可以进行回滚。

二、 面向文档(Document-Oriented)数据库

面向文档数据库会将数据以文档的形式储存。每个文档都是自包含的数据单元,是一系列数据项的集合。每个数据项都有一个名称与对应的值,值既可以是简单的数据类型,如字符串、数字和日期等;也可以是复杂的类型,如有序列表和关联对象。数据存储的最小单位是文档,同一个表中存储的文档属性可以是不同的,数据可以使用XML、JSON或者JSONB等多种形式存储。

产品:MongoDB、CouchDB、RavenDB

有谁在使用:SAP (MongoDB)、Codecademy (MongoDB)、Foursquare (MongoDB)、NBC News (RavenDB)

适用的场景

1. 日志。企业环境下,每个应用程序都有不同的日志信息。Document-Oriented数据库并没有固定的模式,所以我们可以使用它储存不同的信息。

2. 分析。鉴于它的弱模式结构,不改变模式下就可以储存不同的度量方法及添加新的度量。

不适用场景

在不同的文档上添加事务。Document-Oriented数据库并不支持文档间的事务,如果对这方面有需求则不应该选用这个解决方案。

三、 列存储(Wide Column Store/Column-Family)数据库

列存储数据库将数据储存在列族(column family)中,一个列族存储经常被一起查询的相关数据。举个例子,如果我们有一个Person类,我们通常会一起查询他们的姓名和年龄而不是薪资。这种情况下,姓名和年龄就会被放入一个列族中,而薪资则在另一个列族中。

产品:Cassandra、HBase

有谁在使用:Ebay (Cassandra)、Instagram (Cassandra)、NASA (Cassandra)、Twitter (Cassandra and HBase)、Facebook (HBase)、Yahoo!(HBase)

适用的场景

1. 日志。因为我们可以将数据储存在不同的列中,每个应用程序可以将信息写入自己的列族中。

2. 博客平台。我们储存每个信息到不同的列族中。举个例子,标签可以储存在一个,类别可以在一个,而文章则在另一个。

不适用场景

1. 如果我们需要ACID事务。Vassandra就不支持事务。

2. 原型设计。如果我们分析Cassandra的数据结构,我们就会发现结构是基于我们期望的数据查询方式而定。在模型设计之初,我们根本不可能去预测它的查询方式,而一旦查询方式改变,我们就必须重新设计列族。

四、 图(Graph-Oriented)数据库

图数据库允许我们将数据以图的方式储存。实体会被作为顶点,而实体之间的关系则会被作为边。比如我们有三个实体,Steve Jobs、Apple和Next,则会有两个“Founded by”的边将Apple和Next连接到Steve Jobs。

产品:Neo4J、Infinite Graph、OrientDB

有谁在使用:Adobe (Neo4J)、Cisco (Neo4J)、T-Mobile (Neo4J)

适用的场景

1. 在一些关系性强的数据中

2. 推荐引擎。如果我们将数据以图的形式表现,那么将会非常有益于推荐的制定

不适用场景

不适合的数据模型。图数据库的适用范围很小,因为很少有操作涉及到整个图。

转自:http://www.csdn.net/article/2013-07-24/2816330-how-to-choose-nosql-db

Twemproxy——针对MemCached与Redis的代理

 Twemproxy  Twemproxy——针对MemCached与Redis的代理已关闭评论
3月 182013
 
本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2012/12/twemproxy

 

 

Twemproxy是一个代理服务器,可以通过它减少MemcachedRedis服务器所打开的连接数。

Twemproxy有何用途呢?它可以:

  • 通过代理的方式减少缓存服务器的连接数
  • 自动在多台缓存服务器间共享数据
  • 通过不同的策略与散列函数支持一致性散列
  • 通过配置的方式禁用失败的结点
  • 运行在多个实例上,客户端可以连接到首个可用的代理服务器
  • 支持请求的流式与批处理,因而能够降低来回的消耗

Redis的创建者Salvatore Sanfilippo(@antirez)撰写了一篇文章,介绍了如何通过Twemproxy在开启Redis-cluster特性前就让Redis集群发挥作用,而在大多数情况下都不会丧失太多的性能:

Twemproxy的强大之处在于可以通过配置的方式让它禁用掉失败的结点,同时还能在一段时间后进行重试,抑或使用指定的键->服务器映射。这意味着在将Redis用作数据存储时,它可以对Redis数据集进行分片(禁用掉结点驱逐);在将Redis用作缓存时,它可以启用结点驱逐以实现简单的高可用性。

Twemproxy速度很快,真的很快,它几乎与直接访问Redis速度一样快。我敢说在最差的情况下,性能也只不过才损失20%而已。


我对性能问题唯一的想法是当在多个实例上使用命令时,我觉得MGET还有改进空间。

Twemproxy早在今年初由Twitter开源,它最开始支持Memcached,最近又添加了对Redis的支持。Twitter使用了大量的缓存服务器,每秒会发送300k的tweet;可以看看这篇介绍Real-Time Delivery Architecture At Twitter以了解更多信息。

查看英文原文:Twemproxy – Proxy For MemCached And Redis

 
 

安装配置及其它资料参考:

 在去年的 QCon London2012 大会上,Twitter 发表了题为 《Timelines @ Twitter》的演讲,里面提到以 Redis 作为其 timeline 的主要存储,目前目测全球范围内,Twitter 可能是 Redis 的最大用户了(或者是新浪微博?)。

  而今天我们要说的这个 Twemproxy,是 Twitter 开源出来的 Redis 和 Memcached 代理。

  功能介绍

  我们知道,无论是 Memcached 还是当前的 Redis,其本身都不具备分布式集群特性,当我们有大量 Redis 或 Memcached 的时候,通常只能通过客户端的一些数据分配算法(比如一致性哈希),来实现集群存储的特性。

  而 Twemproxy 通过引入一个代理层,可以将其后端的多台 Redis 或 Memcached 实例进行统一管理与分配,使应用程序只需要在 Twemproxy 上进行操作,而不用关心后面具体有多少个真实的 Redis 或 Memcached 存储。

  在 Redis 的 Cluster 方案还没有正式推出之前,通过 Proxy 的方式来实现存储集群可能是最好的选择了。更何况 Twemproxy 是通过 Twitter 自身得到了充分检验的产品。

  性能

  根据 Redis 作者的测试结果,在大多数情况下,Twemproxy 的性能相当不错,直接操作 Redis 相比,最多只有 20% 的性能损失。这对于它带来的好处来说真的是微不足道了。唯一可能还有待改进的是其 MGET 操作的效率,其性能只有直接操作 Redis 的 50%。

  安装与配置

  Twemproxy 的安装有点小麻烦,主要命令如下:

apt-get install automake
apt-get install libtool
git clone git://github.com/twitter/twemproxy.git       cd twemproxy
autoreconf -fvi
./configure --enable-debug=log
make
src/nutcracker -h

  通过上面的命令就算安装好了,然后是具体的配置,下面是一个典型的配置

    redis1:
      listen: 0.0.0.0:9999 #使用哪个端口启动 Twemproxy
      redis: true #是否是 Redis 的 proxy
      hash: fnv1a_64 #指定具体的 hash 函数
      distribution: ketama #具体的 hash 算法
      auto_eject_hosts: true #是否在结点无法响应的时候临时摘除结点
      timeout: 400 #超时时间(毫秒)
      server_retry_timeout: 2000 #重试的时间(毫秒)
      server_failure_limit: 1 #结点故障多少次就算摘除掉
      servers: #下面表示所有的 Redis 节点(IP:端口号:权重)
       - 127.0.0.1:6379:1 - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 - 127.0.0.1:6382:1

    redis2:
      listen: 0.0.0.0:10000
      redis: true
      hash: fnv1a_64
      distribution: ketama
      auto_eject_hosts: false
      timeout: 400
      servers:
       - 127.0.0.1:6379:1 - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 - 127.0.0.1:6382:1

  你可以同时开启多个 Twemproxy 实例,它们都可以进行读写,这样你的应用程序就可以完全避免所谓的单点故障。

  问题与不足

  Twemproxy 由于其自身原理限制,有一些不足之处,如:

  • 不支持针对多个值的操作,比如取 sets 的子交并补等(MGET 和 DEL 除外)
  • 不支持 Redis 的事务操作
  • 出错提示还不够完善

  更多

  关于 Twemproxy 的介绍可以看这里:http://antirez.com/news/44

  Twemproxy 项目地址:https://github.com/twitter/twemproxy

 

ubuntu下redis安装配置

 redis, ubuntu  ubuntu下redis安装配置已关闭评论
2月 052013
 

wget http://redis.googlecode.com/files/redis-2.2.4.tar.gz
也可以到redis.io官网下载最新的包

tar -zxf redis-2.2.4.tar.gz
cd redis-2.2.4
make
sudo make install
2. 配置init脚本:

wget https://github.com/ijonas/dotfiles/raw/master/etc/init.d/redis-server
wget https://github.com/ijonas/dotfiles/raw/master/etc/redis.conf
如果错误认证,添加参数 –no-check-certificate

sudo mv redis-server /etc/init.d/redis-server
sudo chmod +x /etc/init.d/redis-server
sudo mv redis.conf /etc/redis.conf

3. 初始化用户和日志路径
第一次启动Redis前,建议为Redis单独建立一个用户,并新建data和日志文件夹
sudo useradd redis
sudo mkdir -p /var/lib/redis
sudo mkdir -p /var/log/redis
sudo chown redis.redis /var/lib/redis
sudo chown redis.redis /var/log/redis

4、设置开机自动启动,关机自动关闭
sudo update-rc.d redis-server defaults

5. 启动Redis:
sudo /etc/init.d/redis-server start

6.启动客户端连接
/usr/local/bin/redis-cli

添加一个服务
#sudo update-rc.d 服务名 defaults 99
删除一个服务
#sudo update-rc.d 服务名 remove
临时重启一个服务
#/etc/init.d/服务名 restart
临时关闭一个服务
#/etc/init.d/服务名 stop
临时启动一个服务
#/etc/init.d/服务名 start

要在虚拟机下使用redis,需要在redis.conf配置文件中加入really-use-vm true

转自: http://who0168.blog.51cto.com/253401/626345