持久化、主从问题
- (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
- (a) Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。
- (b) Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
- © Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
- (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
- (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
- (4) 尽量避免在压力很大的主库上增加从库
- (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。
Hashtag(可以实现批量操作)
Redis计算槽时并非只简单的计算键值内容,当键值内容包括大括号时,则只计算括号内的内容(Hashtag)。比如:key为user:{10000}:books,计算hash值只计算10000。
Redis事务
Redis事务是一些列redis命令的集合:watch redisKey;multi …exec。
生产上采用的是Redis Cluster集群架构,不同的key是有可能分配在不同的Redis节点上的,在这种情况下Redis的事务机制是不生效的。其次,Redis事务不支持回滚操作,简直是鸡肋!所以基本不用!
Redis的多数据库机制
Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,单机下的redis可以支持16个数据库(db0 ~ db15)。
但是,在Redis Cluster集群架构下只有一个数据库空间,即db0。因此,我们没有使用Redis的多数据库功能!
Redis集群机制不足的地方
- 键的批量操作支持有限,比如mset, mget,如果多个键映射在不同的槽,就不支持了
- 键事务支持有限,当多个key分布在不同节点时无法使用事务,同一节点是支持事务
- 键是数据分区的最小粒度,不能将一个很大的键值对映射到不同的节点
- 不支持多数据库,只有0,select 0
- 复制结构只支持单层结构,不支持树型结构
Redis集群模式下,如何进行批量操作
如果执行的key数量比较少,就不用mget了,就用串行get操作。如果真的需要执行的key很多,就使用Hashtag保证这些key映射到同一台redis节点上。
如果你用的是Proxy分片集群架构,例如Codis这种,会将mget/mset的多个key拆分成多个命令发往不同得redis实例。
Redis做读写分离有什么问题
不做读写分离。我们用的是Redis Cluster的架构,是属于分片集群的架构。而redis本身在内存上操作,不会涉及IO吞吐,即使读写分离也不会提升太多性能,Redis在生产上的主要问题是考虑容量,单机最多10-20G,key太多降低redis性能.因此采用分片集群结构,已经能保证了我们的性能。其次,用上了读写分离后,还要考虑主从一致性,主从延迟等问题,徒增业务复杂度。
大文本数据必须压缩再存储
对于大文本【+超过 500 字节】写入到 Redis 时,一定要压缩后存储。大文本数据存入 Redis,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪。
线上 Redis 禁止使用 Keys 正则匹配操作
redis 是单线程处理,在线上 KEY 数量较多时,操作效率极低【时间复杂度为 O(N)】,该命令一旦执行会严重阻塞线上其它命令的正常请求,而且在高 QPS 情况下会直接造成 Redis 服务崩溃!如果有类似需求,请使用 scan 命令代替!
线上禁止使用 monitor 命令
实时打印出 Redis 服务器接收到的命令,调试用。在高并发条件下,会存在内存暴增和影响 Redis 性能的隐患。
与tair的对比选型
1、公司可运维性
2、数据结构类型,明显redis数据结构多
3、数据量,redis数据存在内存,肯定没有tair的数据量大
4、安全性,tair数据有持久化,一般不丢数据。redis的持久化相对差
5、性能的话,redis好点,毕竟内存读写。redis支持的value的大小更大(理论上1G 256M)
6、都没有单点。tair的config node也有备份节点
如何借助 有序集合 实现多维排序
有序集合默认情况下只能根据一个因子score进行排序。如此一来,局限性就很大。
例如:热门排行榜需要按照下载量&最近更新时间&其他因子排序,即类似数据库中的ORDER BY downloadcount, updatetime DESC。那这样的需求如果用有序集合该如何实现呢?
事实上很简单,思路就是将涉及排序的多个维度的列通过一定的方式转换成一个特殊的列,即result = function(x, y, z),即x,y,z是三个排序因子,例如下载量、时间等,通过自定义函数function()计算得到result,将result作为有序集合中的score的值,就能实现任意维度的排序需求了。
点评:
- redis cluster对mget、mset支持的不够友好,几乎是不能使用(1.可以采用hash tag解决;2.业务代码并发get操作)
- redis事务本身不支持回滚的,在redis cluster模式由于不同的key可能分散到不同节点,这种情况下事务是不生效的
为什么很多人说 Redis 事务为何不支持原子性?
1、Redis 事务不支持事务回滚机制
中间一个命令执行失败后,不会阻断,后面的命令还会继续执行
示例:下面的例子中,总共执行4个命令,其中第3个命令会报错,但是不影响后续第4个命令的执行,可以通过最后的一个查询命令看出来。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set a ab
QUEUED
127.0.0.1:6379(TX)> set b bc
QUEUED
127.0.0.1:6379(TX)> lpop a ha
QUEUED
127.0.0.1:6379(TX)> set c cc
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) (error) ERR value is out of range, must be positive
4) OK
127.0.0.1:6379> get c
"cc"
2、Redis通过强校验命令的合法性, 某种意义上是支持原子性的。
在事务开始后,用户可以输入事务要执行的命令;在命令入事务队列前,会对命令进行检查,如果命令不存在或者是命令参数不对,则会返回错误可客户端,并且修改客户端状态。当后面客户端执行 EXEC 命令时,服务器就会直接拒绝执行此事务了。
但是Redis 事务不支持检查那些程序员造成的逻辑错误。例如对 String 类型的键执行对 HashMap 类型的操作!
示例:下面的例子中,总共4个命令,第3个命令语法错误(与前面的示例区别就在于这里语法错误,前面语法正确,但是key为a的val类型不是list,不能进行rpop操作),最终会发现那些命令正确的语句也没有得到成功执行。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set q qq
QUEUED
127.0.0.1:6379(TX)> set w ww
QUEUED
127.0.0.1:6379(TX)> sett eeeeee
(error) ERR unknown command `sett`, with args beginning with: `eeeeee`,
127.0.0.1:6379(TX)> set r rr
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get q
(nil)
127.0.0.1:6379> get r
(nil)
参考文章 :
https://www.cnblogs.com/fanguangdexiaoyuer/p/10246550.html
https://www.cnblogs.com/Howinfun/p/12774398.html