高并发数据表的处理

botao2690 2018-07-14 06:27:02
想法:
数据库中有一个基础业务表,存在高并发的情况,姑且命名为 T_Base .
我打算将此表放到内存中,一分钟和数据库同步一次(包括读取和更新)

这样在高并发的时候,只需要读取此内存表或更新此内存表。(多线程)
需要如何设计?请教
...全文
1014 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
编程有钱人了 2018-07-18
  • 打赏
  • 举报
回复
qq_42717901 2018-07-17
  • 打赏
  • 举报
回复
是的,需要结合业务场景。
有效利用服务器的内存资源。
botao2690 2018-07-16
  • 打赏
  • 举报
回复
特别感谢【以专业开发人员为伍】的建议。
botao2690 2018-07-16
  • 打赏
  • 举报
回复
感谢
我的业务场景是读远大于写,所以我基本设计思路如下:
1、缓存基础表
2、读取数据时,首先读取缓存,如果缓存没有,则读取数据库
3、更新数据时,首先更新数据库,如果更新成功则更新缓存

这样提高读取的速度,同时保持缓存和数据库的一致性。采用支持多线程的ConcurrentDictionary集合类
  • 打赏
  • 举报
回复
“定时同步”这就意味着,你原来能够准实时处理的业务逻辑,现在会因为本地脏数据而产生糟糕的用户体验问题。这种东西不遇到实际问题时容易说大话以为“没事儿,用户能忍”。都是基本技术的差别造成的。
  • 打赏
  • 举报
回复
几种测试时 --> 集中测试时

只有那些简单的“小配置”才会整表下载。所以缓存这个名词儿容易标题党,真正的技术在于细节。
  • 打赏
  • 举报
回复
Redis 对于服务器开发来说,应该是在你设计服务器集群架构时才考虑(而且也不是一开始就一定考虑)这类。否则就使用你的进程本地缓存。

即使是弄一个额外的 memorycached 或者 redis 之类的缓存服务,你要知道,真正数据量稍微大一点的系统读写和搜索也是针对细粒度的数据的。你想一下,每一分钟都有几千个甚至进程同时下载某个、整个数据表,这是什么设计?这肯定是在办公室里小 OA 的思路产生的设计,而不是互联网思维。

当一个表的数据命中率只有5%甚至更低的时候,你的每一个前端每分钟去把垃圾数据全都抖动下载一遍?这个代价可能远远大于缓存的好处。甚至在逢年过节或者几种测试时,把一个项目搞死,使得业务处理崩溃。
正怒月神 2018-07-16
  • 打赏
  • 举报
回复
引用 13 楼 botao2690 的回复:
感谢各位回复,这个程序以前的应用场景是本地的,设备不多,没有性能问题。
现在用户要求上云,支持个几千台设备感觉还可以,但再多就要重构了。重构的思路没想好。
现在的想法是将原来面向数据库的读取基础数据部分放到内存中,减少对数据库的访问,通过定时同步持久化数据。

可以啊,那区分开来就是,数据放到缓存,所有对于这个表的增删改,都在缓存操作。
然后每隔一段时间吧缓存,整个更新导数据库就好了。
botao2690 2018-07-16
  • 打赏
  • 举报
回复
感谢各位回复,这个程序以前的应用场景是本地的,设备不多,没有性能问题。
现在用户要求上云,支持个几千台设备感觉还可以,但再多就要重构了。重构的思路没想好。
现在的想法是将原来面向数据库的读取基础数据部分放到内存中,减少对数据库的访问,通过定时同步持久化数据。

正怒月神 2018-07-16
  • 打赏
  • 举报
回复
基础业务表
是读多余写吧?
那就无所谓了。
sdfgrtyu 2018-07-16
  • 打赏
  • 举报
回复
引用 1 楼 botao2690 的回复:
使用 BlockingCollection 如何?

完全可以啊,,,,
wanghui0380 2018-07-16
  • 打赏
  • 举报
回复
数据库中有一个基础业务表,存在高并发的情况,姑且命名为 T_Base

我表示你的先分析好,为啥作为个Base类的“基础业务表”,会有并发?什么样的并发?

作为基础业务这类东西,变更比读要慢的多,少的多。所以本质上其实很难有什么真正的“高并发读写”。因为更改频率实际很少。就像你自己的方案-------我打算一分钟同步一次,也就是说你觉着1分钟变更一次都不会对系统产生什么影响,这种东西算不上高并发
botao2690 2018-07-16
  • 打赏
  • 举报
回复
是的,需要结合业务场景。
有效利用服务器的内存资源。很赞。
  • 打赏
  • 举报
回复
缓存往往也是业务流程设计的一部分。例如开发一个某大集团某项目的绩效评分系统,那么复杂的计算中,可能多个子模块中反复使用到了“某个元哦员工的画像集合”信息,那么第一次计算出来这个用户画像时,就可以放到内存中,而以后任意模块(在很短时间内)重复使用这个信息是就可以首先查询同样员工的画像集合。所以这里的业务key就是“员工Id+用户画像指标库名称”的组合。所以缓存是缓存了业务计算程序的结果,而不是底层数据库记录。

所以我再次强调,缓存系统设计其实并不是什么把整个数据库、数据表放到内存里。而是根据业务过程来设计缓存系统。
  • 打赏
  • 举报
回复
常见的业务事件经常重复发生,于是需要缓存。比如说10000次读取 csdn 的 .net 某论坛的第一页列表,才会有一次写(更新),那么就应该把这个论坛的第一页的查询结果缓存起来。然后当这个论坛有新的回复时(发生了数据更改事件时),立刻清除首页列表缓存。那么即使是不同的业务key 所创建的缓存单元里边,都有重复的关于某个帖子标题的内容,也没有关系。

并不是把几千万帖子的数据表缓存,而是根据业务key 来创建缓存单元。
  • 打赏
  • 举报
回复
引用 18 楼 botao2690 的回复:
感谢
我的业务场景是读远大于写,所以我基本设计思路如下:
1、缓存基础表
2、读取数据时,首先读取缓存,如果缓存没有,则读取数据库
3、更新数据时,首先更新数据库,如果更新成功则更新缓存

这样提高读取的速度,同时保持缓存和数据库的一致性。采用支持多线程的ConcurrentDictionary集合类


缓存设计的 key 应该是业务查询 key,比如说类似开发 csdn 时那么应该以“论坛板块+页号”为一个缓存单元的主键,而不是把整个数据表缓存起来。

当查询业务数据时,首先查看相同 key 的缓存但愿是否存在,如果不存在则实际去查询数据库,并且用查询结果创建本地缓存(此时可以设这 Duration 为1分钟)。那么更高级的其实是要想办法实现一个服务器 push 机制,是的缓存单元跟服务器 push 的某些关键字(例如是更改了数据的表的名称)关联起来,当服务气推送某些事件关键字时,相关的缓存单元就自动清除了。所以缓存系统设计的技术在于设计缓存依赖项技术(最初最简单地才是 Duration 参数设置),而并不是简单地把数据缓存到本地、就叫做缓存。

缓存就要提高缓存命中率,如果下载过多数据那么命中率就超级低、就没有必要缓存。所以宁可牺牲处理速度和空间,也要避免下载无用的数据到缓存里。一个命中率达到90%的缓存肯定比命中率只有0.5%的缓存,更可以多花点时间来设计、多花点运行时时间去动态优化。缓存 key 是以上述业务相关的查询细节条件为设计核心的,并不是说定时下载整个数据库表的所有数据。所以你想的定时下载表数据的思路有点想当然。仅仅对于“配置表”等小表可以这样下载。对于大表或者经常更新的表,你的前端使用缓存时应该是从业务 key 设计的细节入手,而不是从整个表这么粗放的角度考虑。
木舟遥 2018-07-16
  • 打赏
  • 举报
回复
然而并没有权限
木舟遥 2018-07-16
  • 打赏
  • 举报
回复
我就试试自己能不能删除自己的回答
  • 打赏
  • 举报
回复
所谓的“一分钟同步一次”,以及所谓的“同步业务表”,其实都不是高并发、缓存的真正的设计概念。真正需要高并发访问、缓存的,是细粒度的东西。比如说曾经使用过的 sql 语句作为key,将查询结果 value 缓存起来。

缓存是有代价的,如果缓存了垃圾,那么就需要不断“全局抖动”去更新完全无用的垃圾。那么你搞的东西其实是个废柴。
baidu_27549073 2018-07-15
  • 打赏
  • 举报
回复
最简单的方式是redis。
加载更多回复(7)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧