SlideShare une entreprise Scribd logo
1  sur  26
基于共享内存的 Key-Value 存
           储
                     —— 财经行情 API 架构优化实
                     践


                                  娄振林




07/09/12
主要内容




             行情 API 及旧架构介绍



             行情 API 架构优化




 07/09/12
行情 API


             •   5 秒内整个财经系统所有实时数据自动刷新
             •   利用 H TML 标签轻松定义数据格式
             •   支持单只股票行情和排行榜等多种展现方式
             •   接口里整合了行情里 6 个品种的实时行情、排
                 行榜以及统计数据




  07/09/12
基于 To kyo C a b ine t 的 ng inx c 模块

                       数据更新                                                                                      数据更新
                                                            Me mc a c he
                                                             S e rve r
                       数据更新                                                                                      数据更新
                                               H as h .48                          H as h .1 8




                                       A p is e rver                             A p is e rver




       A p ic lie nt           A p ic lie nt                  A p ic lie nt                      A p ic lie nt       A p ic lie nt



     TokyoCabinet             TokyoCabinet                  TokyoCabinet                   TokyoCabinet            TokyoCabinet



          Ng inx                  Ng inx                        Ng inx                           Ng inx                 Ng inx
      ( C mo d ule )          ( C mo dule )                 ( C mo d ule )                   ( C mo dule )          ( C mo dule )

                                                               Lo ad B alan c e 1 63 1 68 1 71 23 1 37 1 85
                                                            H TTP Re q ue s t

   07/09/12
行情 A P I 架构优化



              nginx + ngx_lua + redis

              nginx + tmpfs

              nodejs

              基于共享内存的 key-value 存储( shm_map )

              基于 shm_map 的 nginx c 模块




  07/09/12
ng inx + ng x_lua + re d is



                                                                            Ng inx
                                                                         ( ng x_lua )


                                                         pipeline read
                                                                            Ng inx
                                                                         ( ng x_lua )

  subscribe       A P I C lie nt       write
              ( ja va p ro c e s s )           re d is
                                                                            Ng inx
                                                                         ( ng x_lua )




                                                                            Ng inx
                                                                         ( ng x_lua )



        在并发高时, redis 吃内存,并且一直不释放。如果内存不够, redis 会使用
        swap

   07/09/12
ng inx + tmp fs



                                                                          Ng inx



                                                              read file
                                                                          Ng inx


  subscribe       A P I C lie nt       write file
              ( ja va p ro c e s s )                tmp fs
                                                                          Ng inx
                                                    0000001
                                                    1399001
                                                    0000010
                                                    ……
                                                    ……
                                                                          Ng inx




         多进程并发读写问题,以及打开的文件描述符过多


   07/09/12
no d e js


    a. master 进程订阅,然后分发给 worker 进程,数据以 map 形式存储在 worker
    进程内。
                                                      nodejs
                                                     (worker)



                                          dispatch
                                                      nodejs
                                                     (worker)

                subscribe     no d e js
                            ( mas te r)
                                                      nodejs
                                                     (worker)

 分发: nodejs 使用管道实现。
 会有两次内核态到用户态的数据复制。
                                                      nodejs
                                                     (worker)


               数据延迟,各个 worker 的数据可能不一致;上下文切换频繁
               ; cpu 负载高

    07/09/12
no d e js


   b. master 进程订阅,然后通过 redis 分发给 worker 进程,数据以 map 形式存储
   在 worker 进程内。
                                                                nodejs
                                                               (worker)



                                                   subscribe
                                                                nodejs
    subscribe                                                  (worker)
                  no d e js   publish
                                         re d is
                ( mas te r)
                                        q ue ue

                                                                nodejs
                                                               (worker)




                                                                nodejs
                                                               (worker)



               数据延迟的现象没有了,但是 cpu 负载高和上下文切换频繁的
               情况依然存在
    07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


      共享内存的实现原理:
               将多个进程的地址空间的一部分映射到同一块物理内存

              进程 A                                     进程 B
0XFFFFFFFF
              虚拟地址空间                                  虚拟地址空间
                              页          物理内存空间   页
                       虚拟地址   表   物理地址            表

                                          共享内存




0X00000000




   07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


    设计目标:
                内存操作
                一个进程写,多个进程读,无锁
                错误日志,便于定位 bug
                持久化




    模块划分:
              内存池
              HashMap




  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     内存池:
         以 8n 字节进行分配,比如:申请 5 字节,内存池调整为 8 字节
         共享内存空间布局

             初始时                 运行一段时间后
                   未分配空间          已分配空间    未分配空间




              已分配空间布局

                    占用块    空闲块




              将空闲内存组织成多条空闲块链

  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     空闲块列表:

                                                                NULL



             索引表             0          1            2            3    ……             n

                   8 字节                     24 字节                            8n 字节
                    header       data       header       data                header       data



                    header       data       header       data



                    header       data

     空闲块链


                                                                NULL

                                                                        struct header{
                                                                                    free_block   *next;
                                                                                    free_block   *prev;
                                                                                    int          index;
                                                                        };
  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_alloc :
              对应大小的空闲块链不存在,直接从未分配空间分配
              以分配 32 字节为例, m_alloc(m_pool, 30)



                    已分配空间                      未分配空间


                              unalloc_p




                    已分配空间     header    data        未分配空间


                                       data     unalloc_p




  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_alloc :
              存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除
              以分配 8 字节为例, m_alloc(m_pool, 5)


                                                            NULL



                         0          1            2            3    ……            n

               8 字节                     24 字节                           8n 字节
                header       data       header       data               header       data



                header       data       header       data



     tail       header       data




                                                            NULL


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_alloc :
              存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除
              以分配 8 字节为例, m_alloc(m_pool, 5)


                                                            NULL



                         0          1            2            3    ……            n

               8 字节                     24 字节                           8n 字节
                header       data       header       data               header       data



                header       data       header       data



     tail       header       data




                                                            NULL


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_alloc :
              存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除
              以分配 8 字节为例, m_alloc(m_pool, 5)


                                                            NULL



                         0          1            2            3    ……            n

               8 字节                     24 字节                           8n 字节
                header       data       header       data               header       data



     tail       header       data       header       data




                                                            NULL


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_free :
             将空闲块从头部插入到对应的空闲块链中
             以释放 32 字节为例, m_free(m_pool, ptr)


                                                              NULL



                           0          1            2            3    ……            n

                 8 字节                     24 字节                           8n 字节
                  header       data       header       data               header       data



     tail         header       data       header       data




                                                              NULL


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     m_free :
             将空闲块从头部插入到对应的空闲块链中
             以释放 32 字节为例, m_free(m_pool, ptr)


                                                              NULL



                           0          1            2            3             ……              n

                 8 字节                     24 字节                                      8n 字节
                  header       data       header       data          header   data   header       data



     tail         header       data       header       data




                                                              NULL


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     HashMap :
    支持 put 、 get 、 remove 、 keys 、 iter 、 size 、 contains 操作
    通过红黑树解决碰撞

                                                             NULL




             Bulk List           0       1       2            3           ……                 n



                         entry                   entry


             entry               entry   entry           entry



     entry        entry                              entry        entry   struct entry{
                                                                                          entry        *left;
                                                                                          entry        *right;
                                                                                          entry        *parent;
                                                     NULL                                 rb_color_t   color;
                                                                                          const char   *key;
                                                                                          val_t        value;
                                                                          };


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     Benchmark
      分别向 tc 和 shm_map put 100000 条大小分别为 2KB 、 20KB 、 200KB
      机器配置:虚拟机, 4 核 E5640 2.67GHz , 4G




                                                 254.924s 254.991s




                             24.785s   25.211s
             2.539s 2.590s




  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


    a. node binding
                                                   nodejs
                                                  (worker)



                                            get
                                                   nodejs
  subscribe                                       (worker)
                no d e js   put
                                  shm map
              ( mas te r)

                                                   nodejs
                                                  (worker)




                                                   nodejs
                                                  (worker)



         上下文切换的次数明显降低了 40-50% , cpu 负载还是很高


  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


    b. python binding
                                                  tornado
                                                  (worker)



                                            get
                                                  tornado
  subscribe                                       (worker)
                no d e js   put
                                  shm map
              ( mas te r)

                                                  tornado
                                                  (worker)




                                                  tornado
                                                  (worker)




         cpu 负载的确降低了,但是在高并发、大数据量的情况下, tornado 抛出
         一堆 socket 错误

  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


    c. Nginx C module
                                                   Ng inx
                                               ( C mo d ule )


                                         get
                                                   Ng inx
                                               ( C mo d ule )

 subscribe              put
              nodejs          s hm map
                                                   Ng inx
                                               ( C mo d ule )




                                                   Ng inx
                                               ( C mo d ule )




  07/09/12
基于共享内存的 ke y- va lue 存储( s hm_ma p )


     各种方案的性能测试
       响应内容大小是 150KB+ , 20000 并发下,请求 20000 次
       机器配置:虚拟机, 4 核 E5640 2.67GHz , 4G


                         方案                     QPS
                  TC + nginx C module           1300+
                  Redis + lua + nginx           900+
                        nodejs                  1100+
               Shm_map + nginx C module         1400+




  07/09/12
Q&A
           Thank you!!!



07/09/12

Contenu connexe

Similaire à 基于共享内存的Key value存储——财经行情api架构优化实践

淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
Wensong Zhang
 
淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
lovingprince58
 
淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
drewz lin
 
淘宝对象存储与Cdn系统到服务
淘宝对象存储与Cdn系统到服务淘宝对象存储与Cdn系统到服务
淘宝对象存储与Cdn系统到服务
drewz lin
 
前端本地应用程序网络
前端本地应用程序网络前端本地应用程序网络
前端本地应用程序网络
tblanlan
 
Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统
智杰 付
 
淘宝图片存储与Cdn系统
淘宝图片存储与Cdn系统淘宝图片存储与Cdn系统
淘宝图片存储与Cdn系统
Dai Jun
 
Taobao 海量图片存储与CDN系统02
Taobao 海量图片存储与CDN系统02Taobao 海量图片存储与CDN系统02
Taobao 海量图片存储与CDN系统02
lovingprince58
 
Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统
Michael Zhang
 

Similaire à 基于共享内存的Key value存储——财经行情api架构优化实践 (15)

Cdc@ganji.com
Cdc@ganji.comCdc@ganji.com
Cdc@ganji.com
 
淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
 
Taobao base
Taobao baseTaobao base
Taobao base
 
淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
 
淘宝软件基础设施构建实践
淘宝软件基础设施构建实践淘宝软件基础设施构建实践
淘宝软件基础设施构建实践
 
淘宝对象存储与Cdn系统到服务
淘宝对象存储与Cdn系统到服务淘宝对象存储与Cdn系统到服务
淘宝对象存储与Cdn系统到服务
 
Taobao图片存储与cdn系统到服务
Taobao图片存储与cdn系统到服务Taobao图片存储与cdn系统到服务
Taobao图片存储与cdn系统到服务
 
前端本地应用程序网络
前端本地应用程序网络前端本地应用程序网络
前端本地应用程序网络
 
Interactive Data Language
Interactive Data LanguageInteractive Data Language
Interactive Data Language
 
Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统
 
淘宝图片存储与Cdn系统
淘宝图片存储与Cdn系统淘宝图片存储与Cdn系统
淘宝图片存储与Cdn系统
 
Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统
 
Taobao 海量图片存储与CDN系统02
Taobao 海量图片存储与CDN系统02Taobao 海量图片存储与CDN系统02
Taobao 海量图片存储与CDN系统02
 
Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统Taobao海量图片存储与cdn系统
Taobao海量图片存储与cdn系统
 
稳定、高效、低碳 -淘宝软件基础设施构建实践
稳定、高效、低碳  -淘宝软件基础设施构建实践稳定、高效、低碳  -淘宝软件基础设施构建实践
稳定、高效、低碳 -淘宝软件基础设施构建实践
 

基于共享内存的Key value存储——财经行情api架构优化实践

  • 1. 基于共享内存的 Key-Value 存 储 —— 财经行情 API 架构优化实 践 娄振林 07/09/12
  • 2. 主要内容  行情 API 及旧架构介绍  行情 API 架构优化 07/09/12
  • 3. 行情 API • 5 秒内整个财经系统所有实时数据自动刷新 • 利用 H TML 标签轻松定义数据格式 • 支持单只股票行情和排行榜等多种展现方式 • 接口里整合了行情里 6 个品种的实时行情、排 行榜以及统计数据 07/09/12
  • 4. 基于 To kyo C a b ine t 的 ng inx c 模块 数据更新 数据更新 Me mc a c he S e rve r 数据更新 数据更新 H as h .48 H as h .1 8 A p is e rver A p is e rver A p ic lie nt A p ic lie nt A p ic lie nt A p ic lie nt A p ic lie nt TokyoCabinet TokyoCabinet TokyoCabinet TokyoCabinet TokyoCabinet Ng inx Ng inx Ng inx Ng inx Ng inx ( C mo d ule ) ( C mo dule ) ( C mo d ule ) ( C mo dule ) ( C mo dule ) Lo ad B alan c e 1 63 1 68 1 71 23 1 37 1 85 H TTP Re q ue s t 07/09/12
  • 5. 行情 A P I 架构优化  nginx + ngx_lua + redis  nginx + tmpfs  nodejs  基于共享内存的 key-value 存储( shm_map )  基于 shm_map 的 nginx c 模块 07/09/12
  • 6. ng inx + ng x_lua + re d is Ng inx ( ng x_lua ) pipeline read Ng inx ( ng x_lua ) subscribe A P I C lie nt write ( ja va p ro c e s s ) re d is Ng inx ( ng x_lua ) Ng inx ( ng x_lua ) 在并发高时, redis 吃内存,并且一直不释放。如果内存不够, redis 会使用 swap 07/09/12
  • 7. ng inx + tmp fs Ng inx read file Ng inx subscribe A P I C lie nt write file ( ja va p ro c e s s ) tmp fs Ng inx 0000001 1399001 0000010 …… …… Ng inx 多进程并发读写问题,以及打开的文件描述符过多 07/09/12
  • 8. no d e js a. master 进程订阅,然后分发给 worker 进程,数据以 map 形式存储在 worker 进程内。 nodejs (worker) dispatch nodejs (worker) subscribe no d e js ( mas te r) nodejs (worker) 分发: nodejs 使用管道实现。 会有两次内核态到用户态的数据复制。 nodejs (worker) 数据延迟,各个 worker 的数据可能不一致;上下文切换频繁 ; cpu 负载高 07/09/12
  • 9. no d e js b. master 进程订阅,然后通过 redis 分发给 worker 进程,数据以 map 形式存储 在 worker 进程内。 nodejs (worker) subscribe nodejs subscribe (worker) no d e js publish re d is ( mas te r) q ue ue nodejs (worker) nodejs (worker) 数据延迟的现象没有了,但是 cpu 负载高和上下文切换频繁的 情况依然存在 07/09/12
  • 10. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  共享内存的实现原理:  将多个进程的地址空间的一部分映射到同一块物理内存 进程 A 进程 B 0XFFFFFFFF 虚拟地址空间 虚拟地址空间 页 物理内存空间 页 虚拟地址 表 物理地址 表 共享内存 0X00000000 07/09/12
  • 11. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  设计目标:  内存操作  一个进程写,多个进程读,无锁  错误日志,便于定位 bug  持久化  模块划分:  内存池  HashMap 07/09/12
  • 12. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  内存池:  以 8n 字节进行分配,比如:申请 5 字节,内存池调整为 8 字节  共享内存空间布局 初始时 运行一段时间后 未分配空间 已分配空间 未分配空间  已分配空间布局 占用块 空闲块  将空闲内存组织成多条空闲块链 07/09/12
  • 13. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  空闲块列表: NULL 索引表 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data header data header data header data 空闲块链 NULL struct header{ free_block *next; free_block *prev; int index; }; 07/09/12
  • 14. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_alloc :  对应大小的空闲块链不存在,直接从未分配空间分配  以分配 32 字节为例, m_alloc(m_pool, 30) 已分配空间 未分配空间 unalloc_p 已分配空间 header data 未分配空间 data unalloc_p 07/09/12
  • 15. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_alloc :  存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除  以分配 8 字节为例, m_alloc(m_pool, 5) NULL 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data header data header data tail header data NULL 07/09/12
  • 16. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_alloc :  存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除  以分配 8 字节为例, m_alloc(m_pool, 5) NULL 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data header data header data tail header data NULL 07/09/12
  • 17. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_alloc :  存在对应大小的空闲块链,返回空闲块链的尾部空闲块,并从链中删除  以分配 8 字节为例, m_alloc(m_pool, 5) NULL 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data tail header data header data NULL 07/09/12
  • 18. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_free :  将空闲块从头部插入到对应的空闲块链中  以释放 32 字节为例, m_free(m_pool, ptr) NULL 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data tail header data header data NULL 07/09/12
  • 19. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  m_free :  将空闲块从头部插入到对应的空闲块链中  以释放 32 字节为例, m_free(m_pool, ptr) NULL 0 1 2 3 …… n 8 字节 24 字节 8n 字节 header data header data header data header data tail header data header data NULL 07/09/12
  • 20. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  HashMap :  支持 put 、 get 、 remove 、 keys 、 iter 、 size 、 contains 操作  通过红黑树解决碰撞 NULL Bulk List 0 1 2 3 …… n entry entry entry entry entry entry entry entry entry entry struct entry{ entry *left; entry *right; entry *parent; NULL rb_color_t color; const char *key; val_t value; }; 07/09/12
  • 21. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  Benchmark  分别向 tc 和 shm_map put 100000 条大小分别为 2KB 、 20KB 、 200KB  机器配置:虚拟机, 4 核 E5640 2.67GHz , 4G 254.924s 254.991s 24.785s 25.211s 2.539s 2.590s 07/09/12
  • 22. 基于共享内存的 ke y- va lue 存储( s hm_ma p ) a. node binding nodejs (worker) get nodejs subscribe (worker) no d e js put shm map ( mas te r) nodejs (worker) nodejs (worker) 上下文切换的次数明显降低了 40-50% , cpu 负载还是很高 07/09/12
  • 23. 基于共享内存的 ke y- va lue 存储( s hm_ma p ) b. python binding tornado (worker) get tornado subscribe (worker) no d e js put shm map ( mas te r) tornado (worker) tornado (worker) cpu 负载的确降低了,但是在高并发、大数据量的情况下, tornado 抛出 一堆 socket 错误 07/09/12
  • 24. 基于共享内存的 ke y- va lue 存储( s hm_ma p ) c. Nginx C module Ng inx ( C mo d ule ) get Ng inx ( C mo d ule ) subscribe put nodejs s hm map Ng inx ( C mo d ule ) Ng inx ( C mo d ule ) 07/09/12
  • 25. 基于共享内存的 ke y- va lue 存储( s hm_ma p )  各种方案的性能测试  响应内容大小是 150KB+ , 20000 并发下,请求 20000 次  机器配置:虚拟机, 4 核 E5640 2.67GHz , 4G 方案 QPS TC + nginx C module 1300+ Redis + lua + nginx 900+ nodejs 1100+ Shm_map + nginx C module 1400+ 07/09/12
  • 26. Q&A Thank you!!! 07/09/12