Yêu cầu thg 6 26, 11:36 SA 590 1 1
  • 590 1 1
+2

Bài toán tính lượt view một bài viết (mạng xã hội)?

Chia sẻ
  • 590 1 1

**Bài toán tính lượt view một bài viết (mạng xã hội)? ** Mình đang muốn tìm hiểu thêm về góc nhìn cách tính lượt view cho 1 bài viết. Mình có một vài câu hỏi như sau

Không biết ở dự án các mọi người đang xử lý bài toán tình lượt view như nào?. Có thể liệt kê vài steps ra giúp mình.

ý tưởng của mình đang làm là như này. các bạn có nhận xét và có cách nào tối ưu hơn không

// mình tính cả 2 case là chưa click vào bài viết và lướt qua thấy bài viết

String result = jedis.set(Ip, "hits", "NX", "EX", 20); // Redis, đại loại là nếu IP này đang tồn tại thì không set và thời gian sống của nó là 20 giây , Không chơi kiểu cứ refresh 1 lần

là tính một lượt view (giả sử sau 20 giây sau mà xem mình cho phép số view +1)

if("Ok".equa(result)){ set Id video và tăng view lên 1 }

Cần lưu ý những vấn đề gì ?

2.1 Mình sẽ dùng địa chỉ IP để tính lượt view (nhưng trường hợp ví dụ như ở trong cùng một công ty, cùng một địa chỉ IP, vậy liệu chẳng lẽ mình không tính số view

cho những người cùng địa chỉ IP), không biết chỗ này các dự án thường làm như nào, ??

2.2. Giả sử trường hợp mấy người kia cùng một địa chỉ IP mà xem bài viết thì mình vẫn muốn tăng lượt view thì làm như nào ?

2.4. Nếu còn vấn đề gì cần lưu ý thì mong các bạn giới thiệu cho mình thêm góc nhìn? (This is so important)

                 => Mục đích là để cho cái task này hoàn thiện và tối ưu nhất có thể, nên mong các bạn thoải mái chia sẻ những vấn đề liên quan đến chức năng này nhé ạ

1 CÂU TRẢ LỜI


Đã trả lời thg 6 26, 12:56 CH
Đã được chấp nhận
+6

3 cách để đếm.

  1. Đếm ngay khi mở web. Chỉ có header hoặc cookie được gửi đi. Nếu dùng cookie thì có thể bỏ qua được vấn đề IP.
  2. Đếm sau khi mở web, call api đếm riêng. Cái này thì dễ tùy biến, thường đi theo cả tracking.
  3. Google Analytics.

Phía server: Cũng không cần thiết phải redis. Nếu dùng cookie thì chỉ việc check ở request rồi call lệnh increase (nếu redis). Không dùng cookie thì có thể thêm tham số browser agent cùng với ip, hash rồi lưu cờ ở redis, có thể tăng một chút độ chính xác.

Gọi api chủ động thì muốn làm gì thì làm rồi.

Chia sẻ
thg 6 26, 2:05 CH

Bạn cho mình hỏi trường hợp mình sử dụng redis để quản lý số lượng view.

Cụ thể là nếu yêu cầu của mình là mỗi khi người dùng vào một bài viết nào đó và muốn xem lượt view là bao nhiêu ?

  1. Trong redis mình sẽ không bao h clear nó đi đúng không ạ,

  2. Mình đang nghĩ là mình sẽ tính toán xem cái bài viết đó ví dụ 30 ngày sau không được user (người mà đăng bài ) xem lại thì mình sẽ clear cache đi

Thường thì các dự án họ đang làm như nào bạn nhỉ?

Avatar refacore @refacore
thg 6 26, 3:16 CH

@Huyennv Thực tế thì cũng ko cần redis. Lưu sql cũng đc. Việc đếm lượt ko quá nặng và thường thì sql cũng đủ gánh. Lượt view thường cũng ko phải realtime nên sql cũng không chiu tải nhiều (cache được thời gian dài). Dùng Redis thì vẫn cần phải lưu lại lượt view vào đâu đó lâu dài, như chạy job cuối ngày lưu lại vào sql chẳng hạn.

Theo mình thì lưu sql và cache in memory cũng ok rồi (số lượng bài viết thường không nhiều, đặc biệt bài viết active đang có nhiều người đọc). Đơn giản, tin cậy.

Cũng chưa thấy ai reset lượt view sau 30 ngày, trừ game 😄. Kể cả 30 ngày thì vẫn cần lưu dài hạn. Redis không đủ tin cậy để làm việc đó.

Trong trường hợp là monitoring hay telemetry thì có nhiều tool sẵn có, không chỉ đếm mà còn log luôn.

thg 6 26, 3:30 CH

Cám ơn bạn nhiều nhé. Nhưng mà giả dụ leader của mình vẫn yêu cầu lưu vào redis, thì khi nào mình nên clear cho cái phần trước đó mình lưu(key: id bài viết, value : lượt view) nhỉ. vẫn câu hỏi cũ, trường hợp common nhất thì các hệ thống đang xử lý case này như nào nhỉ, 😃 😄 bạn có thể lấy ví dụ giúp mình được không

Avatar refacore @refacore
thg 6 27, 3:32 SA

@Huyennv phải có yêu cầu đặc biệt thì mới phải làm căng thế. BT các hệ thống cũng chỉ persist xuống db nào đấy rồi cache lại thôi. Wordpress chẳng hạn. Hoặc youtube.

Dễ thấy nhất là view của youtube thường bị cache. Nó có mâu thuẫn thế này:

  1. trang ít view, con số view nhỏ thì việc cập nhật số view thường xuyên có vẻ được để ý.
  2. trang nhiều view, con số chính xác là không quan trọng, thường người ta hiển thị con số rút ngắn như 12K, 12M. Một con số chi tiết kiểu 12.345 là không ý nghĩa hơn 12K.

Việc kiểm soát số view theo thời gian thực có thể ví dụ trong ecommerce. Khi muốn sale sản phẩm, muốn show số người xem theo thời gian thực để thúc đẩy khách hàng. Ngoài push notification để update số view, khách cũng thường refresh trang liên tục. Thực tế thì có lẽ push notification là cũng đủ hiệu quả. Con số view chỉ là tương đối.

Cần làm rõ 2 vấn đề trong câu hỏi của bạn:

  1. Redis không phải là DB duy nhất trong hệ thống, vẫn cần 1 db để lưu giữ số view lâu dài.
  2. Clear Redis không phải xóa số view của trang. Hệ thống sẽ tải lại số view từ DB dài hạn (persistence storage, db sơ cấp).

Có 3 cách sử dụng Redis:

  1. Đơn thuần là Cache. Khi có lượt view, hệ thống tăng số trong db dài hạn (db sơ cấp). Khi query, hệ thống lấy từ Redis (cache), không có sẽ query DB sơ cấp.
  2. Chạy song song Redis và DB sơ cấp. Khi có lượt view, hệ thống increase số view cả Redis lẫn db sơ cấp. Khi Redis reset, load lại dữ liệu view này từ DB theo 2 cách:
  • On demand, query đến đâu load từ db sơ cấp đến đó.
  • Fetch-all - load tất cả từ db bằng Job hoặc trigger.
  1. Cập nhật Redis trước, định kì cập nhật lại db sơ cấp. Khi có request, increase Redis count. Job chạy update lại db sau. Khi redis reset thì fetch-all từ db sơ cấp.

Kết luận:

  • Chưa tìm ra ứng dụng thực tế của việc lưu số view vào Redis. Số view chỉ là con số tương đối, không cần sử dụng kĩ thuật phức tạp để xử lý.
thg 7 1, 2:19 CH

@refacore Sorry bạn, mình giờ mới rep được, Bạn giải thích khá dễ hiểu. Mình đã hiểu các ý bạn nói, mình muốn làm rõ thêm ý nữa là:

  1. Với trường hợp như thế thì khi nào thì là phù hợp để clear cache đi (giả xử như không có yêu cầu cụ thể mà mình muốn làm cho tối ưu nhất có thể)
  2. Và tại sao ?

Cám ơn bạn nhiều

Avatar refacore @refacore
thg 7 2, 1:04 SA

@Huyennv Trong trường hợp hệ thống chạy bt thì cũng khó kiếm ra lý do để clear cache. Xét với 3 cách thiết kế ở trên:

1. Redis đơn thuần là cache. Cache có expire time được cài đặt theo 3 cách:

  • Absolute - đặt thời gian tồn tại cố định cho cache, cache sẽ tự clear sau khi đến hạn.
  • Sliding - đặt thời gian clear cache nếu cache không được truy cập nữa, hay mỗi lần cache được truy cập thì thời gian hết hạn của cache được đặt lại về số ban đầu. Đối với sliding thì có vấn đề là nếu cache được truy cập liên tục thì sẽ không bao giờ được clear => nhu cầu clear cache thủ công
  • Cache validation: cài đặt một callback xử lý việc clear cache khi đạt một điều kiện nào đấy. Cái này thường được kết hợp cùng expire time. Đối với tính lượt view, một dependency để invalidate cache có thể là khi số view đạt đến hàng nghìn thì clear cache, hoặc một trick là rand trong range 100, 1000, nếu bằng 1 thì clear.

2. Redis chạy song song

Về cơ bản thì phương án này vẫn là cache, nhưng cái khác là số đếm được cập nhật song song giữa redis và lưu trữ trong DB. Do Redis được cập nhật trực tiếp như DB nên không cần validate cache. Redis bị xóa thì có thể do mất điện, shutdown hệ thống để maitain hay update.

3. Lưu Redis trước rồi backup lại trên DB sau

Trường hợp này thì không có lý do gì để xóa redis cả (xóa là mất dữ liệu). Chỉ có 1 trường hợp cần là khi hệ thống gián đoạn (maitainance, update ...), Redis sẽ mất hết dữ liệu và cần reload lại từ DB. (Redis lưu dữ liệu trong RAM nên mất điện là mất hết).

thg 7 2, 2:29 SA

@refacore Mình hiểu rồi, cám ơn bạn đã đóng góp cho cộng đồng, mình tin là bài viết này sẽ còn có giá trị cho nhiều người khác sau này nữa.

thg 10 28, 7:30 SA

@refacore Mình muốn làm rõ hơn một chút về vấn đề dùng cookies để khặc phục vấn đề nhiều người dùng chung một giải địa chỉ IP

Bạn có thể làm rõ hơn một chút chỗ này giúp mình được không?

Mong được nhận câu trả lời từ bạn!

Avatar refacore @refacore
thg 10 30, 1:39 SA

@Huyennv xử lý địa chỉ IP là bài toán khác, không phụ thuộc vào cookies hay redis, sql. Các thông tin từ browser gửi đi là không đủ để phân biệt các máy tính chung 1 dải IP. Cách giải quyết có thể:

  1. Với mỗi lần truy cập, sinh một UUID cho máy đó, lưu vào local storage (hoặc cookies). Nó sẽ như UserId dùng để phân biệt. Thông tin này đi theo máy và có thể bị xóa bởi người dùng. Không hiệu quả trong chế độ ẩn danh.
  2. Dùng fingerprint. Có một vài thư viện js hỗ trợ. Nó sẽ hash các thông tin có thể có từ browser để sinh ra một đoạn mã. Cách này không đảm bảo sẽ phân biệt được toàn bộ các máy cùng dải IP, nhưng hoạt động được trong chế độ ẩn danh.
thg 10 30, 8:02 SA

@refacore Em Hiểu rồi. Cám ơn Bác nhé ạ

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí