Nosql三步曲

3,456 views

Published on

从NoSQL产品的选型,到对选出来的产品(Redis)进行了解,最后使用该产品(Redis),就好像“海选”-->“相亲"-->“结婚”的过程。

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,456
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
67
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Nosql三步曲

  1. 1. NoSQL三步曲 朱国能-Gallen.Chu http://www.84zhu.com guoneng.zhu@gmail.com
  2. 2. 目录 海选 • NoSQL选型 • Redis面对面 相亲 结婚 • Redis实践
  3. 3. 海选- NoSQL选型
  4. 4. NoSQL选型 用MongoDB的一句设计哲学开始• Databases are specializing – the “one size fits all” approach no longer applies.
  5. 5. 我们为什么要使用NOSQL非关系数据库? High • 对数据库高并发读写的需求 performance • 对海量数据的高效率存储和访 Huge Storage 问的需求 High Scalability • 对数据库的高可扩展性和高可 && High Availability 用性的需求
  6. 6. 关系数据库的很多主要特性? 数据库事务一致性需求 数据库的写实时性和读实时性需求 对复杂的SQL查询,特别是多表关联查询的需求
  7. 7. 选型原则 高并发快 速读写 CPU资源 可用性 消耗 文档齐全/ 一致性 社区活跃 原则 客户端 可扩展 /API支持 海量数据 …… 的高效读 写
  8. 8. 选型原则 Consistency CAP Availability Tolerance of network Partition Basically 三大基石 Available BASE Soft state Eventually 最终一致性 consistent 理论依据 五分钟法则
  9. 9. NoSQL比较
  10. 10. 我们需要什么?• 高并发快速读写• 海量数据高效读写• 高可用性• 排行、热门、分类数据结构灵活• 简单的API、客户端支持• 文档完善、社区活跃• 支持良好、版本更新活跃• 可以容忍最终一致性• 可以容忍client分区、集群
  11. 11. 相亲-Redis面对面
  12. 12. What is Redis? What is sponsored by:• 全名 REmote DIctionary Server• Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.• key value store? cache? memory database? data structure server?
  13. 13. 优点• FAST both read and write• data can dump to disk• master-slave• many useful data structure• Active community/ Antirez
  14. 14. 缺点• Physical memory limit• Auto-sharding / Cluster• Scale ability• Automatic failover switch
  15. 15. Fast• 根据 Redis 官方的测试结果:在 50 个并发的情况下请求 10w 次,写 的速度是 110000次/s,读的速度是 81000 次/s• 测试环境:• 1. 50 个并发,请求 100000 次• 2. 读和写大小为 256bytes 的字符串• 3. Linux2.6 Xeon X3320 2.5GHz 的服务器上• 4. 通过本机的 loopback interface 接口上执行• 地址: • http://code.google.com/p/redis/wiki/Benchmarks • http://redis.io/topics/benchmarks
  16. 16. 性能对比 小数据:500W条数据;每个value:100 bytes
  17. 17. 性能对比 大数据:500W条数据;每个value:20k bytes
  18. 18. Why Fast• Libevent。和Memcached不同,Redis并没有选择libevent。Libevent 为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及 牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现 了自己的epoll event loop(4)。业界不少开发者也建议Redis使用另外 一个libevent高性能替代libev,但是作者还是坚持Redis应该小巧并去 依赖的思路。一个印象深刻的细节是编译Redis之前并不需要执行 ./configure。• CAS问题。CAS是Memcached中比较方便的一种防止竞争修改资源 的方法。CAS实现需要为每个cache key设置一个隐藏的cas token, cas相当value版本号,每次set会token需要递增,因此带来CPU和内 存的双重开销,虽然这些开销很小,但是到单机10G+ cache以及 QPS上万之后这些开销就会给双方相对带来一些细微性能差别(5)。
  19. 19. Useful data structure键(keys) 值(values)page:index.html <html><head>[...] Stringusers_logged_in_today { 1, 2, 3, 4, 5 } Setslatest_post_ids [201, 204, 209,..] Listusers_and_scores joe ~ 1.3483 ZSets bert ~ 93.4 fred ~ 283.22 chris ~ 23774.17
  20. 20. DUMP• snapshot(RDB) – 定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久 化之后如果出现crash则会丢失一段数据。• AOP(append only mode) – 写入内存数据的同时将操作命令保存到日志文件,在一个并发更 改上万的系统中,命令日志是一个非常庞大的数据,管理维护成 本非常高,恢复重建时间会非常长,这样导致失去aof高可用性本 意。
  21. 21. RDB• Fork一个进程,利用copy on write原理,遍历所有的db的hash table,进行整库的dump• Save命令,shutdown命令,slave启动都会触发• 利用LZF进行压缩• 持久化触发条件:• #sava 900 1• #save 300 10• #save 60
  22. 22. BGREWRITEAOF• 避免aof文件过大• 2.4版本增加自动的bgrewriteaof• auto-aof-rewrite-min-size 64mb• auto-aof-rewrite-percentage 100• 手动bgrewriteaof
  23. 23. Best redo-logo• 当redisserver异常crash掉的时候,重启时将会进行如下的操作: – 假如只配置了aof,启动时加载aof文件 – 假如同事配置了rdb/aof,启动时只加载aof文件 – 假如只配置rdb,启动时将加载dump文件• 在非创建快照期间追加redo-log,在完成快照后清除redo-log
  24. 24. 存储模式• VM方式:将数据分页存放,由应用(如Redis)或者操作系统(如Varnish)将访 问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存 中。应用实现VM缺点是代码逻辑复杂,如果业务上冷热数据边界并不分明, 则换入换出代价太高,系统整体性能低。不少抢鲜的网友在微博上也反馈过 使用VM种种不稳定情况。 (目前Redis使用的方式)• 磁盘方式:所有的数据读写访问都是基于磁盘,由操作系统来只能的缓存访 问的数据。由于现代操作系统都非常聪明,会将频繁访问的数据加入到内存 中,因此应用并不需要过多特殊逻辑。MongoDB就是这种设计方式。这种方 式也有一些已知的缺点,比如操作MMap写入磁盘由操作系统控制,操作系 统先写哪里后写哪里应用并不知情,如果写入过程中发生了crash则数据一致 性会存在问题。 (作者称其为MongoDB的方式)• Diskstore:实际原理和mysql+memcache方式类似,只不过将两者功 能合二为一到一个底层服务中,简化了调用。(作者打算使用的新方 式,alpha版本,Demo)
  25. 25. Replication• master可以有多个slave• 除了多个slave连到相同的master外,slave也可以连接其他slave形成 图状结构• 主从复制不会阻塞master。也就是说当一个或多个slave与master进 行初次同步数据时,master可以继续处理client发来的请求。相反 slave在初次同步数据时则会阻塞不能处理client的请求。• 主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用 于client的读请求,比如sort操作可以使用slave来处理。也可以用来 做简单的数据冗余• 可以在master禁用数据持久化,只需要注释掉master 配置文件中的 所有save配置,然后只在slave上配置数据持久化• slaveof 172.16.3.35 6379 #指定master的ip和端口• slave重连无增量复制,slave表重建
  26. 26. Author
  27. 27. 应用场景• 取最新N个数据的操作• 排行榜应用,取TOP N操作• 需要精准设定过期时间的应用• 计数器应用• Uniq操作,获取某段时间所有数据排重值• 实时系统,反垃圾系统• Pub/Sub构建实时消息系统• 构建队列系统• 缓存
  28. 28. 2.4版本改进• 对Sorted Sets的内存优化• RDB文件持久化提速• 提供批量写入功能• 改用jemalloc的内存分配模式• 减少 copy-on-write 使用• INFO输出内容增强• VM机制彻底废弃• 总的来说2.4版本会在各方面有性能上的提升
  29. 29. Why 6379 Why? 63796379在是手机按键上MERZ对应的号码MERZ取自意大利歌女Alessia Merz的名字
  30. 30. 结婚- Redis实践
  31. 31. Redis容量规划及建议• 数据项: value保存的内容是什么,如用户资料• 业务数据类型: 如String, List, set• 数据大小: 如100字节• 记录数: 如100万条(决定是否需要拆分)• 数据增多如何扩展?• 读写瓶颈如何扩展?• 不仅要规划还要严密监控!• sharding策略与HA(rolling/pre-sharding/双写/多slave)• 使用Pipeline减小网络IO/原子操作• Redis的最佳使用方式是 in-memory
  32. 32. Redis数据库的键值设计(一) mysql> select * from login; +---------+----------------------------+-------------------------+--------------------------------------+ | user_id | name | login_times | last_login_time | +---------+----------------------------+-------------------------+--------------------------------------+ | 1 | Doug.Wang | 5| 2011-10-01 00:00:00 | | 2 | Jeff.Tu | 1| 2011-10-01 00:00:00 | | 3 | Gallen.Chu | 2| 2011-11-01 00:00:00 | +----------+---------------------------+-------------------------+-------------------------------------+ key表名:主键值:列名 Set login:1:login_times 5 Set login:2:login_times 1 Set login:3:login_times 2 Set login:1:last_login_time 2011-10-1 Set login:2:last_login_time 2011-10-1 Set login:3:last_login_time 2011-11-1 Set login:1:name “Doug.Wang” Set login:2:name “Jeff.Tu”” Set login:3:name “Gallen.Chu”
  33. 33. Redis数据库的键值设计(二)排序需求zadd post:post_times 15 1zadd post:post_times 11 2zadd post:post_times 28 3#对该应用的评论次数自增1ret = r.zincrby(“post:post_times", 1, app_id)获得评论次数最多的应用,逆序排列取的排名第N的应用ret = r.zrevrange(“post:post_times", 0, N-1)
  34. 34. Redis数据库的键值设计(三)Set app:1:name "冒泡音乐盒"Set app:2:name "股票指南"Set app:3:name "幻想三国"sadd appTag:application 1sadd appTag:application 2sadd appTag:tools 2sadd appTag:webgame 3即属于application又属于tools的应用?inter_list = redis.sinter("appTag:application", "appTag:tools")即属于application,但不属于tools的应用inter_list = redis.sdiff("appTag:application", "appTag:tools")属于application和属于tools的书的合集?inter_list = redis.sunion("appTag:application", "appTag:tools")
  35. 35. Example• A_start 10, A_end 20• B_start 30, B_end 40• redis 127.0.0.1:6379> zadd ranges 10 A_start (integer) 1• redis 127.0.0.1:6379> zadd ranges 20 A_end (integer) 1• redis 127.0.0.1:6379> zadd ranges 30 B_start (integer) 1• redis 127.0.0.1:6379> zadd ranges 40 B_end (integer) 1• redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1 1) "A_end“• redis 127.0.0.1:6379> zrangebyscore ranges (25 +inf LIMIT 0 1 1) "B_start"
  36. 36. 使用hset代替set对象:skyappid : 1name : 天气助手appid : 2914created_time : 132013777338 HSET skyapp:1 name “天气助手” HSET skyapp:1 appid 2914 HSET skyapp:1 created_time 132013777338• 结构化数据存取 ---------------------------------------------------• 提高内存使用率 HLEN skyapp:1 == 3 HGET skyapp:1 name == “天气助手” HKEYS skyapp:1 == name , appid, created_time HGETALL skyapp:1 == name => 天气助手 time => 2914 created_time => 132013777338
  37. 37. 使用Pipleline模式•发送多个命令,一次性接收多个命令,减少网络IO次数•服务器将命令结果放进queue,再返回给客户端Client: INCR X Client: INCR XServer: 1 Client: INCR XClient: INCR X Client: INCR XServer: 2 Client: INCR XClient: INCR X Server: 1Server: 3 Server: 2Client: INCR X Server: 3Server: 4 Server: 4
  38. 38. 不要使用VM• Redis VM 不靠谱,作者在2.4版本中已经彻底放弃了VM – 症状: • 代码逻辑复杂 • 系统整体性能低 • 如业务冷热数据边界不分明,换入换出代价太高 • 数据DUMP的时候内存耗光,CPU100% – 方案: • 加大物理内存 • 数据sharding
  39. 39. 集群架构(一) 主从架构• Redis缺少同步机制常见的check point和校验机制• 如果同步转发丢失,一致性无法保证,只有slave重启时全量加载才 能修复 – 方案:主库在内存中运行,从库不提供线上服务只做持久化备份 Master Replication Slave 纯内存 备份、持久化
  40. 40. 集群架构(二) 单机多节点 ( 节点数=CPU - 1 )  分布式缓存 (一致性哈希)Redis1:6380 每天2点 6G redis redisRedis2:6381 每天3点 6GRedis3:6382 每天4点 6G 预留6G redis redis  分时间段 bgrewriteaof  充分提高内存使用率
  41. 41. 集群架构(三) Sharding 数据分片 应用层 sharding R/ R/ R/ W W W master1 master2 master3 slave1 slave2 slave3 备份 备份 备份
  42. 42. 集群架构(四) •All nodes are directly connected with a service channel. •TCP baseport+4000, example 6379 -> 10379. •Node to Node protocol is binary,optimized for bandwidth and speed. •Clients talk to nodes as usually, using ascii protocol, with minor additions. •Nodes dont proxy queries.
  43. 43. Redis客户端• 各种语言客户端支持。• Jedis,ShardJedis,ShardJedisPipeline• 支持客户端分布式,ShardJedis。一致性哈希算 法,采用TreepMap<String,ShardInfo>存储redis 节点,murmur哈希函数计算key和server的值。 默认虚拟160个节点,支持权重配置。• 连接池管理。JedisPool。
  44. 44. WEB界面管理工具• 一个PHP的Redis WEB管理工具phpRedisAdmin• 项目地址:https://github.com/ErikDubbelboer/phpRedisAdmin• 演示demo:http://dubbelboer.com/phpRedisAdmin/
  45. 45. 附:参数说明(一)配置项 说明daemonize no 是否以后台进程运行,默认为nopidfile 如以后台进程运行,则需指定一个pid,默认/var/run/redis.pidport 6379 监听端口,默认为6379bind 127.0.0.1 绑定主机IP,默认值为127.0.0.1timeout 300 超时时间,默认为300(秒)loglevel 日志记录等级,有4个可选值,debug,verbose(默认值),notice,warninglogfile 日志记录方式,默认值为stdoutslaveof 当本机为从服务时,设置主服务的IP及端口。在启动时,REDIS会自动从 MASTER上把数据先同步过来,而无需我们手动进行。MASTER上每有一次 落地保存,会自动向SLAVE进行同步。masterauth 当本机为从服务时,设置主服务的连接密码requirepass 连接密码maxclients 最大客户端连接数,默认不限制maxmemory 设置最大内存,达到最大内存设置后,Redis会先尝试清除已到期或即将到期 的Key,当此方法处理后,任到达最大内存设置,将无法再进行写入操作。
  46. 46. 附:参数说明(二)配置项 说明save 900 1 900秒内有1个改变,save 300 10 300秒内有10个改变,save 60 10000 60秒内有10000个改变, redis就会内存中的key保存到数据库文件中去rdbcompression 存储至本地数据库时是否压缩数据,默认为yesdbfilename 本地数据库文件名,默认值为dump.rdbdir 本地数据库存放路径,默认值为 ./Appendonly 是否在每次更新操作后进行日志记录,开启AOFappendfilename 更新日志文件名,默认值为appendonly.aofappendfsync 新日志条件,共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘, always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示 每秒同步一次(默认)hash-max- 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,hash将以zipmap-entries 一种特殊的编码方式(大大减少内存使用)来存储hash-max- hash中一个元素的最大值zipmap-value
  47. 47. 附:参数说明(三)配置项 说明vm-enabled 是否使用虚拟内存,默认值为novm-swap-file 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享vm-max-memory 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory 设置多小,所有索引数据都是内存存储的 (Redis的索引数据就是keys),也就 是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。 默认值为0vm-page-size 虚拟内存文件以块存储,默认每块32bytesvm-pages 虚拟内在文件的最大数,默认134217728vm-max-threads 可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置 为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延 迟,但是对数据完整性有很好的保证.
  48. 48. 附:Redis扩展阅读我怎么获得更多,更全的Redis信息?1、http://code.google.com/p/redis/2、http://redis.io3、http://antirez.com/4、http://blog.nosqlfan.com/tags/Redis5、http://redis.readthedocs.org/en/2.4/index.html6、http://www.google.com
  49. 49. Q&A

×