对于第一个问题,设计一个schema->(messageID,likedCount),记录每条微博的点赞数。messageID是微博的编号,likedCount是该微博的点赞人数。但是这里有两个问题需要解决,第一是并发,第二是数据量。
每条微博都有可能有很多人同时点赞,为了保证点赞人数精确就需要保证likedCount++是原子 *** 作,这个可以由应用程序来实现,也可以用redis的事务来实现(如果redis有事务机制或者自增功能的话),但是我觉得为了性能考虑,也可以不用实现原子 *** 作,具体原因就不展开了。
每天都上亿可能更多的微博内容产生,这样就会有上亿个新的(messageID,likedCount)生成,这样的数据量是比较大的,单机数据库比较难提供高效的服务,所以需要采取sharding的功能(有时候也叫分表分库),可能根据messageID把这些schema分散到十个或者更多的shards上(据说,sina微博有600个节点,如何三个节点组成一个shard,就有200个shards),这样每个shard处理的请求就只有原来的十分之一,从而就能提高服务的性能。
关于点赞人列表的设计,一般来说,可能想到的schema是(messageID,userID),但是这样的设计有一个小问题,就是有些大发的微博可能会得到几十万的点赞,这样就会产生几十万个条数据,这样数据有点多,读取起来可能也慢。所以可以用这样一个schema(messageID,partID,userIDs),让一个messageID对于多个userID,同时比对应太多的userID,所以加入一个新的partID,一个part存1000个userID,这样几十万个点赞,只需要存几百条数据。这样做还有一个好处,用户点击查看点赞人时的,一般都不是完全显示所有点赞人,而是一批一批显示,这样可以一次只读一条数据,就可显示一批点赞用户信息。
你可以把这两个属性按key-value存储到redis中,可以使用redis的incr方法。例如:redis.incr("zan")和redis.incr("cai")这个方法是原子性增加的,是线程安全的,如果之前存在zan和cai会自动加1,如果不存在会自动保存并加1.
应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql,此种情况存在的问题主要是如何保证mysql与redis的数据同步,二者数据同步的关键在于mysql数据库中主键,方案是在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。
String tbname = "login"
//获取mysql表主键值--redis启动时
long id = MySQL.getID(tbname)
//设置redis主键值--redis启动时
redisService.set(tbname, String.valueOf(id))
System.out.println(id)
long l = redisService.incr(tbname)
System.out.println(l)
Login login = new Login
login.setId(l)
login.setName("redis")
redisService.hmset(String.valueOf(login.getId), login)
boolean b = MySQL.insert("insert into login(id,name) values(" + login.getId + ",'" + login.getName + "')")
/**
*
* 队列处理器更新mysql失败:
*
* 清除缓存数据,同时主键值自减
*/
if (!b){
redisService.delKeyAndDecr(tbname, "Login:"+String.valueOf(login.getId))
}
System.out.println(redisService.exists("Login:"+String.valueOf(login.getId)))
System.out.println(redisService.get(tbname))
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)